blob: 9f4bbc97411d2ef8cb9001f07e5a06a4f4b6ef47 [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 Tyner6764d702021-02-12 09:17:23 -060066 // This trace will be picked up in event log
67 trace<level::INFO>("dbusMethod service not found");
68 std::string traceMsgPath = std::string(i_path, maxTraceLen);
69 trace<level::INFO>(traceMsgPath.c_str());
70 std::string traceMsgIface = std::string(i_interface, maxTraceLen);
71 trace<level::INFO>(traceMsgIface.c_str());
Ben Tyner188f1092021-02-01 09:33:06 -060072 }
73 }
74 catch (const sdbusplus::exception::SdBusError& e)
75 {
Ben Tyner6764d702021-02-12 09:17:23 -060076 trace<level::INFO>("dbusMethod exception");
77 std::string traceMsg = std::string(e.what(), maxTraceLen);
78 trace<level::ERROR>(traceMsg.c_str());
Ben Tyner188f1092021-02-01 09:33:06 -060079 }
80
81 return rc;
82}
83
84/** @brief Create a PEL for the specified event type */
85uint32_t createPel(const std::string& i_event,
86 std::map<std::string, std::string>& i_additional,
87 const std::vector<util::FFDCTuple>& i_ffdc)
88{
89 // CreatePELWithFFDCFiles returns plid
90 int plid = 0;
91
92 // Need to provide pid when using create or create-with-ffdc methods
93 i_additional.emplace("_PID", std::to_string(getpid()));
94
95 // Sdbus call specifics
96 constexpr auto interface = "org.open_power.Logging.PEL";
97 constexpr auto function = "CreatePELWithFFDCFiles";
98
99 sdbusplus::message::message method;
100
101 if (0 == dbusMethod(pathLogging, interface, function, method))
102 {
103 try
104 {
105 // append additional dbus call paramaters
106 method.append(i_event, levelPelError, i_additional, i_ffdc);
107
108 // using system dbus
109 auto bus = sdbusplus::bus::new_system();
110 auto response = bus.call(method);
111
112 // reply will be tuple containing bmc log id, platform log id
113 std::tuple<uint32_t, uint32_t> reply = {0, 0};
114
115 // parse dbus reply
116 response.read(reply);
117 plid = std::get<1>(reply); // platform log id is tuple "second"
118 }
119 catch (const sdbusplus::exception::SdBusError& e)
120 {
Ben Tyner6764d702021-02-12 09:17:23 -0600121 trace<level::INFO>("createPel exception");
122 std::string traceMsg = std::string(e.what(), maxTraceLen);
123 trace<level::ERROR>(traceMsg.c_str());
Ben Tyner188f1092021-02-01 09:33:06 -0600124 }
125 }
126
127 return plid; // platform log id or 0
128}
129
130/** @brief Create a PEL from raw PEL data */
131void createPelRaw(const std::vector<uint8_t>& i_buffer)
132{
133 // Create FFDC file from buffer data
134 util::FFDCFile pelFile{util::FFDCFormat::Text};
135 auto fd = pelFile.getFileDescriptor();
Ben Tyner188f1092021-02-01 09:33:06 -0600136
137 auto filePath = pelFile.getPath(); // path to ffdc file
138
Ben Tynerd7006092021-02-05 14:55:52 -0600139 size_t numBytes = write(fd, i_buffer.data(), i_buffer.size());
140 if (i_buffer.size() != numBytes)
141 {
142 std::stringstream traceMsg;
143 traceMsg << filePath.c_str() << " only " << (int)numBytes << " of "
144 << (int)i_buffer.size() << " bytes written";
145 auto strobj = traceMsg.str();
146 trace<level::ERROR>(strobj.c_str());
147 }
148
149 lseek(fd, 0, SEEK_SET);
150
Ben Tyner188f1092021-02-01 09:33:06 -0600151 // Additional data for log
152 std::map<std::string, std::string> additional;
153 additional.emplace("RAWPEL", filePath.string());
154 additional.emplace("_PID", std::to_string(getpid()));
155
156 // dbus specifics
157 constexpr auto interface = "xyz.openbmc_project.Logging.Create";
158 constexpr auto function = "Create";
159
160 sdbusplus::message::message method;
161
162 if (0 == dbusMethod(pathLogging, interface, function, method))
163 {
164 try
165 {
166 // append additional dbus call parameters
167 method.append(eventPelTerminate, levelPelError, additional);
168
169 // using system dbus, no reply
170 auto bus = sdbusplus::bus::new_system();
171 bus.call_noreply(method);
172 }
173 catch (const sdbusplus::exception::SdBusError& e)
174 {
Ben Tyner6764d702021-02-12 09:17:23 -0600175 trace<level::INFO>("createPelRaw exception");
176 std::string traceMsg = std::string(e.what(), maxTraceLen);
177 trace<level::ERROR>(traceMsg.c_str());
Ben Tyner188f1092021-02-01 09:33:06 -0600178 }
179 }
180}
181
182/** @brief Get file descriptor of exisitng PEL */
183int getPel(const uint32_t i_pelId)
184{
185 // GetPEL returns file descriptor (int)
186 int fd = -1;
187
188 // dbus specifics
189 constexpr auto interface = "org.open_power.Logging.PEL";
190 constexpr auto function = "GetPEL";
191
192 sdbusplus::message::message method;
193
194 if (0 == dbusMethod(pathLogging, interface, function, method))
195 {
196 try
197 {
198 // additional dbus call parameters
199 method.append(i_pelId);
200
201 // using system dbus
202 auto bus = sdbusplus::bus::new_system();
203 auto response = bus.call(method);
204
205 // reply will be a unix file descriptor
206 sdbusplus::message::unix_fd reply;
207
208 // parse dbus reply
209 response.read(reply);
210
211 fd = dup(reply); // need to copy (dup) the file descriptor
212 }
213 catch (const sdbusplus::exception::SdBusError& e)
214 {
Ben Tyner6764d702021-02-12 09:17:23 -0600215 trace<level::INFO>("getPel exception");
216 std::string traceMsg = std::string(e.what(), maxTraceLen);
217 trace<level::ERROR>(traceMsg.c_str());
Ben Tyner188f1092021-02-01 09:33:06 -0600218 }
219 }
220
221 return fd; // file descriptor or -1
222}
223
224} // namespace attn