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