blob: 72b637ed0d72105f859bda6df18d942842caf91a [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();
134 write(fd, i_buffer.data(), i_buffer.size());
135 lseek(fd, 0, SEEK_SET);
136
137 auto filePath = pelFile.getPath(); // path to ffdc file
138
139 // Additional data for log
140 std::map<std::string, std::string> additional;
141 additional.emplace("RAWPEL", filePath.string());
142 additional.emplace("_PID", std::to_string(getpid()));
143
144 // dbus specifics
145 constexpr auto interface = "xyz.openbmc_project.Logging.Create";
146 constexpr auto function = "Create";
147
148 sdbusplus::message::message method;
149
150 if (0 == dbusMethod(pathLogging, interface, function, method))
151 {
152 try
153 {
154 // append additional dbus call parameters
155 method.append(eventPelTerminate, levelPelError, additional);
156
157 // using system dbus, no reply
158 auto bus = sdbusplus::bus::new_system();
159 bus.call_noreply(method);
160 }
161 catch (const sdbusplus::exception::SdBusError& e)
162 {
163 std::stringstream ss;
164 ss << "createPelRaw exception: " << e.what();
165 trace<level::INFO>(ss.str().c_str());
166 }
167 }
168}
169
170/** @brief Get file descriptor of exisitng PEL */
171int getPel(const uint32_t i_pelId)
172{
173 // GetPEL returns file descriptor (int)
174 int fd = -1;
175
176 // dbus specifics
177 constexpr auto interface = "org.open_power.Logging.PEL";
178 constexpr auto function = "GetPEL";
179
180 sdbusplus::message::message method;
181
182 if (0 == dbusMethod(pathLogging, interface, function, method))
183 {
184 try
185 {
186 // additional dbus call parameters
187 method.append(i_pelId);
188
189 // using system dbus
190 auto bus = sdbusplus::bus::new_system();
191 auto response = bus.call(method);
192
193 // reply will be a unix file descriptor
194 sdbusplus::message::unix_fd reply;
195
196 // parse dbus reply
197 response.read(reply);
198
199 fd = dup(reply); // need to copy (dup) the file descriptor
200 }
201 catch (const sdbusplus::exception::SdBusError& e)
202 {
203 std::stringstream ss;
204 ss << "getPel exception: " << e.what();
205 trace<level::INFO>(ss.str().c_str());
206 }
207 }
208
209 return fd; // file descriptor or -1
210}
211
212} // namespace attn