blob: 8765f4336ee392932001f6f928a88246de1d38d8 [file] [log] [blame]
Ben Tyner188f1092021-02-01 09:33:06 -06001#include <attn_logging.hpp>
2
3#include <string>
4#include <vector>
5
6namespace attn
7{
8
9/**
10 * Create a dbus method
11 *
12 * Find the dbus service associated with the dbus object path and create
13 * a dbus method for calling the specified dbus interface and function.
14 *
15 * @param i_path - dbus object path
16 * @param i_interface - dbus method interface
17 * @param i_function - dbus interface function
18 * @param o_method - method that is created
19 * @return non-zero if error
20 *
21 **/
22int dbusMethod(const std::string& i_path, const std::string& i_interface,
23 const std::string& i_function,
24 sdbusplus::message::message& o_method)
25{
26 int rc = 1; // assume error
27
28 try
29 {
30 constexpr auto serviceFind = "xyz.openbmc_project.ObjectMapper";
31 constexpr auto pathFind = "/xyz/openbmc_project/object_mapper";
32 constexpr auto interfaceFind = "xyz.openbmc_project.ObjectMapper";
33 constexpr auto functionFind = "GetObject";
34
35 auto bus = sdbusplus::bus::new_system(); // using system dbus
36
37 // method to find service from object path and object interface
38 auto method = bus.new_method_call(serviceFind, pathFind, interfaceFind,
39 functionFind);
40
41 // find the service for specified object path and interface
42 method.append(i_path.c_str());
43 method.append(std::vector<std::string>({i_interface}));
44 auto reply = bus.call(method);
45
46 // dbus call results
47 std::map<std::string, std::vector<std::string>> responseFindService;
48 reply.read(responseFindService);
49
50 // If we successfully found the service associated with the dbus object
51 // path and interface then create a method for the specified interface
52 // and function.
53 if (!responseFindService.empty())
54 {
55 auto service = responseFindService.begin()->first;
56
57 // return the method
58 o_method =
59 bus.new_method_call(service.c_str(), i_path.c_str(),
60 i_interface.c_str(), i_function.c_str());
61
62 rc = 0;
63 }
64 else
65 {
Ben Tyner5ec757b2021-02-09 07:04:58 -060066 std::string traceMsg =
67 "dbusMethod service not found: " + i_path + ", " + i_interface;
68 trace<level::INFO>(traceMsg.c_str());
Ben Tyner188f1092021-02-01 09:33:06 -060069 }
70 }
71 catch (const sdbusplus::exception::SdBusError& e)
72 {
Ben Tyner5ec757b2021-02-09 07:04:58 -060073 std::string traceMsg = "dbusMethod exception: " + std::string(e.what());
74 trace<level::INFO>(traceMsg.c_str());
Ben Tyner188f1092021-02-01 09:33:06 -060075 }
76
77 return rc;
78}
79
80/** @brief Create a PEL for the specified event type */
81uint32_t createPel(const std::string& i_event,
82 std::map<std::string, std::string>& i_additional,
83 const std::vector<util::FFDCTuple>& i_ffdc)
84{
85 // CreatePELWithFFDCFiles returns plid
86 int plid = 0;
87
88 // Need to provide pid when using create or create-with-ffdc methods
89 i_additional.emplace("_PID", std::to_string(getpid()));
90
91 // Sdbus call specifics
92 constexpr auto interface = "org.open_power.Logging.PEL";
93 constexpr auto function = "CreatePELWithFFDCFiles";
94
95 sdbusplus::message::message method;
96
97 if (0 == dbusMethod(pathLogging, interface, function, method))
98 {
99 try
100 {
101 // append additional dbus call paramaters
102 method.append(i_event, levelPelError, i_additional, i_ffdc);
103
104 // using system dbus
105 auto bus = sdbusplus::bus::new_system();
106 auto response = bus.call(method);
107
108 // reply will be tuple containing bmc log id, platform log id
109 std::tuple<uint32_t, uint32_t> reply = {0, 0};
110
111 // parse dbus reply
112 response.read(reply);
113 plid = std::get<1>(reply); // platform log id is tuple "second"
114 }
115 catch (const sdbusplus::exception::SdBusError& e)
116 {
Ben Tyner5ec757b2021-02-09 07:04:58 -0600117 std::string traceMsg =
118 "createPel exception: " + std::string(e.what());
119 trace<level::INFO>(traceMsg.c_str());
Ben Tyner188f1092021-02-01 09:33:06 -0600120 }
121 }
122
123 return plid; // platform log id or 0
124}
125
126/** @brief Create a PEL from raw PEL data */
127void createPelRaw(const std::vector<uint8_t>& i_buffer)
128{
129 // Create FFDC file from buffer data
130 util::FFDCFile pelFile{util::FFDCFormat::Text};
131 auto fd = pelFile.getFileDescriptor();
Ben Tyner188f1092021-02-01 09:33:06 -0600132
133 auto filePath = pelFile.getPath(); // path to ffdc file
134
Ben Tynerd7006092021-02-05 14:55:52 -0600135 size_t numBytes = write(fd, i_buffer.data(), i_buffer.size());
136 if (i_buffer.size() != numBytes)
137 {
138 std::stringstream traceMsg;
139 traceMsg << filePath.c_str() << " only " << (int)numBytes << " of "
140 << (int)i_buffer.size() << " bytes written";
141 auto strobj = traceMsg.str();
142 trace<level::ERROR>(strobj.c_str());
143 }
144
145 lseek(fd, 0, SEEK_SET);
146
Ben Tyner188f1092021-02-01 09:33:06 -0600147 // Additional data for log
148 std::map<std::string, std::string> additional;
149 additional.emplace("RAWPEL", filePath.string());
150 additional.emplace("_PID", std::to_string(getpid()));
151
152 // dbus specifics
153 constexpr auto interface = "xyz.openbmc_project.Logging.Create";
154 constexpr auto function = "Create";
155
156 sdbusplus::message::message method;
157
158 if (0 == dbusMethod(pathLogging, interface, function, method))
159 {
160 try
161 {
162 // append additional dbus call parameters
163 method.append(eventPelTerminate, levelPelError, additional);
164
165 // using system dbus, no reply
166 auto bus = sdbusplus::bus::new_system();
167 bus.call_noreply(method);
168 }
169 catch (const sdbusplus::exception::SdBusError& e)
170 {
Ben Tyner5ec757b2021-02-09 07:04:58 -0600171 std::string traceMsg =
172 "createPelRaw exception: " + std::string(e.what());
173 trace<level::INFO>(traceMsg.c_str());
Ben Tyner188f1092021-02-01 09:33:06 -0600174 }
175 }
176}
177
178/** @brief Get file descriptor of exisitng PEL */
179int getPel(const uint32_t i_pelId)
180{
181 // GetPEL returns file descriptor (int)
182 int fd = -1;
183
184 // dbus specifics
185 constexpr auto interface = "org.open_power.Logging.PEL";
186 constexpr auto function = "GetPEL";
187
188 sdbusplus::message::message method;
189
190 if (0 == dbusMethod(pathLogging, interface, function, method))
191 {
192 try
193 {
194 // additional dbus call parameters
195 method.append(i_pelId);
196
197 // using system dbus
198 auto bus = sdbusplus::bus::new_system();
199 auto response = bus.call(method);
200
201 // reply will be a unix file descriptor
202 sdbusplus::message::unix_fd reply;
203
204 // parse dbus reply
205 response.read(reply);
206
207 fd = dup(reply); // need to copy (dup) the file descriptor
208 }
209 catch (const sdbusplus::exception::SdBusError& e)
210 {
Ben Tyner5ec757b2021-02-09 07:04:58 -0600211 std::string traceMsg = "getPel exception: " + std::string(e.what());
212 trace<level::INFO>(traceMsg.c_str());
Ben Tyner188f1092021-02-01 09:33:06 -0600213 }
214 }
215
216 return fd; // file descriptor or -1
217}
218
219} // namespace attn