xref: /openbmc/openpower-hw-diags/attn/attn_dbus.cpp (revision 6764d70eea47a83adc98c1266dd2f7eb5b7456c8)
1188f1096SBen Tyner #include <attn_logging.hpp>
2188f1096SBen Tyner 
3188f1096SBen Tyner #include <string>
4188f1096SBen Tyner #include <vector>
5188f1096SBen Tyner 
6188f1096SBen Tyner namespace attn
7188f1096SBen Tyner {
8188f1096SBen Tyner 
9188f1096SBen Tyner /**
10188f1096SBen Tyner  * Create a dbus method
11188f1096SBen Tyner  *
12188f1096SBen Tyner  * Find the dbus service associated with the dbus object path and create
13188f1096SBen Tyner  * a dbus method for calling the specified dbus interface and function.
14188f1096SBen Tyner  *
15188f1096SBen Tyner  * @param i_path - dbus object path
16188f1096SBen Tyner  * @param i_interface - dbus method interface
17188f1096SBen Tyner  * @param i_function - dbus interface function
18188f1096SBen Tyner  * @param o_method - method that is created
19188f1096SBen Tyner  * @return non-zero if error
20188f1096SBen Tyner  *
21188f1096SBen Tyner  **/
22188f1096SBen Tyner int dbusMethod(const std::string& i_path, const std::string& i_interface,
23188f1096SBen Tyner                const std::string& i_function,
24188f1096SBen Tyner                sdbusplus::message::message& o_method)
25188f1096SBen Tyner {
26188f1096SBen Tyner     int rc = 1; // assume error
27188f1096SBen Tyner 
28188f1096SBen Tyner     try
29188f1096SBen Tyner     {
30188f1096SBen Tyner         constexpr auto serviceFind   = "xyz.openbmc_project.ObjectMapper";
31188f1096SBen Tyner         constexpr auto pathFind      = "/xyz/openbmc_project/object_mapper";
32188f1096SBen Tyner         constexpr auto interfaceFind = "xyz.openbmc_project.ObjectMapper";
33188f1096SBen Tyner         constexpr auto functionFind  = "GetObject";
34188f1096SBen Tyner 
35188f1096SBen Tyner         auto bus = sdbusplus::bus::new_system(); // using system dbus
36188f1096SBen Tyner 
37188f1096SBen Tyner         // method to find service from object path and object interface
38188f1096SBen Tyner         auto method = bus.new_method_call(serviceFind, pathFind, interfaceFind,
39188f1096SBen Tyner                                           functionFind);
40188f1096SBen Tyner 
41188f1096SBen Tyner         // find the service for specified object path and interface
42188f1096SBen Tyner         method.append(i_path.c_str());
43188f1096SBen Tyner         method.append(std::vector<std::string>({i_interface}));
44188f1096SBen Tyner         auto reply = bus.call(method);
45188f1096SBen Tyner 
46188f1096SBen Tyner         // dbus call results
47188f1096SBen Tyner         std::map<std::string, std::vector<std::string>> responseFindService;
48188f1096SBen Tyner         reply.read(responseFindService);
49188f1096SBen Tyner 
50188f1096SBen Tyner         // If we successfully found the service associated with the dbus object
51188f1096SBen Tyner         // path and interface then create a method for the specified interface
52188f1096SBen Tyner         // and function.
53188f1096SBen Tyner         if (!responseFindService.empty())
54188f1096SBen Tyner         {
55188f1096SBen Tyner             auto service = responseFindService.begin()->first;
56188f1096SBen Tyner 
57188f1096SBen Tyner             // return the method
58188f1096SBen Tyner             o_method =
59188f1096SBen Tyner                 bus.new_method_call(service.c_str(), i_path.c_str(),
60188f1096SBen Tyner                                     i_interface.c_str(), i_function.c_str());
61188f1096SBen Tyner 
62188f1096SBen Tyner             rc = 0;
63188f1096SBen Tyner         }
64188f1096SBen Tyner         else
65188f1096SBen Tyner         {
66*6764d70eSBen Tyner             // This trace will be picked up in event log
67*6764d70eSBen Tyner             trace<level::INFO>("dbusMethod service not found");
68*6764d70eSBen Tyner             std::string traceMsgPath = std::string(i_path, maxTraceLen);
69*6764d70eSBen Tyner             trace<level::INFO>(traceMsgPath.c_str());
70*6764d70eSBen Tyner             std::string traceMsgIface = std::string(i_interface, maxTraceLen);
71*6764d70eSBen Tyner             trace<level::INFO>(traceMsgIface.c_str());
72188f1096SBen Tyner         }
73188f1096SBen Tyner     }
74188f1096SBen Tyner     catch (const sdbusplus::exception::SdBusError& e)
75188f1096SBen Tyner     {
76*6764d70eSBen Tyner         trace<level::INFO>("dbusMethod exception");
77*6764d70eSBen Tyner         std::string traceMsg = std::string(e.what(), maxTraceLen);
78*6764d70eSBen Tyner         trace<level::ERROR>(traceMsg.c_str());
79188f1096SBen Tyner     }
80188f1096SBen Tyner 
81188f1096SBen Tyner     return rc;
82188f1096SBen Tyner }
83188f1096SBen Tyner 
84188f1096SBen Tyner /** @brief Create a PEL for the specified event type */
85188f1096SBen Tyner uint32_t createPel(const std::string& i_event,
86188f1096SBen Tyner                    std::map<std::string, std::string>& i_additional,
87188f1096SBen Tyner                    const std::vector<util::FFDCTuple>& i_ffdc)
88188f1096SBen Tyner {
89188f1096SBen Tyner     // CreatePELWithFFDCFiles returns plid
90188f1096SBen Tyner     int plid = 0;
91188f1096SBen Tyner 
92188f1096SBen Tyner     // Need to provide pid when using create or create-with-ffdc methods
93188f1096SBen Tyner     i_additional.emplace("_PID", std::to_string(getpid()));
94188f1096SBen Tyner 
95188f1096SBen Tyner     // Sdbus call specifics
96188f1096SBen Tyner     constexpr auto interface = "org.open_power.Logging.PEL";
97188f1096SBen Tyner     constexpr auto function  = "CreatePELWithFFDCFiles";
98188f1096SBen Tyner 
99188f1096SBen Tyner     sdbusplus::message::message method;
100188f1096SBen Tyner 
101188f1096SBen Tyner     if (0 == dbusMethod(pathLogging, interface, function, method))
102188f1096SBen Tyner     {
103188f1096SBen Tyner         try
104188f1096SBen Tyner         {
105188f1096SBen Tyner             // append additional dbus call paramaters
106188f1096SBen Tyner             method.append(i_event, levelPelError, i_additional, i_ffdc);
107188f1096SBen Tyner 
108188f1096SBen Tyner             // using system dbus
109188f1096SBen Tyner             auto bus      = sdbusplus::bus::new_system();
110188f1096SBen Tyner             auto response = bus.call(method);
111188f1096SBen Tyner 
112188f1096SBen Tyner             // reply will be tuple containing bmc log id, platform log id
113188f1096SBen Tyner             std::tuple<uint32_t, uint32_t> reply = {0, 0};
114188f1096SBen Tyner 
115188f1096SBen Tyner             // parse dbus reply
116188f1096SBen Tyner             response.read(reply);
117188f1096SBen Tyner             plid = std::get<1>(reply); // platform log id is tuple "second"
118188f1096SBen Tyner         }
119188f1096SBen Tyner         catch (const sdbusplus::exception::SdBusError& e)
120188f1096SBen Tyner         {
121*6764d70eSBen Tyner             trace<level::INFO>("createPel exception");
122*6764d70eSBen Tyner             std::string traceMsg = std::string(e.what(), maxTraceLen);
123*6764d70eSBen Tyner             trace<level::ERROR>(traceMsg.c_str());
124188f1096SBen Tyner         }
125188f1096SBen Tyner     }
126188f1096SBen Tyner 
127188f1096SBen Tyner     return plid; // platform log id or 0
128188f1096SBen Tyner }
129188f1096SBen Tyner 
130188f1096SBen Tyner /** @brief Create a PEL from raw PEL data */
131188f1096SBen Tyner void createPelRaw(const std::vector<uint8_t>& i_buffer)
132188f1096SBen Tyner {
133188f1096SBen Tyner     // Create FFDC file from buffer data
134188f1096SBen Tyner     util::FFDCFile pelFile{util::FFDCFormat::Text};
135188f1096SBen Tyner     auto fd = pelFile.getFileDescriptor();
136188f1096SBen Tyner 
137188f1096SBen Tyner     auto filePath = pelFile.getPath(); // path to ffdc file
138188f1096SBen Tyner 
139d700609cSBen Tyner     size_t numBytes = write(fd, i_buffer.data(), i_buffer.size());
140d700609cSBen Tyner     if (i_buffer.size() != numBytes)
141d700609cSBen Tyner     {
142d700609cSBen Tyner         std::stringstream traceMsg;
143d700609cSBen Tyner         traceMsg << filePath.c_str() << " only " << (int)numBytes << " of "
144d700609cSBen Tyner                  << (int)i_buffer.size() << " bytes written";
145d700609cSBen Tyner         auto strobj = traceMsg.str();
146d700609cSBen Tyner         trace<level::ERROR>(strobj.c_str());
147d700609cSBen Tyner     }
148d700609cSBen Tyner 
149d700609cSBen Tyner     lseek(fd, 0, SEEK_SET);
150d700609cSBen Tyner 
151188f1096SBen Tyner     // Additional data for log
152188f1096SBen Tyner     std::map<std::string, std::string> additional;
153188f1096SBen Tyner     additional.emplace("RAWPEL", filePath.string());
154188f1096SBen Tyner     additional.emplace("_PID", std::to_string(getpid()));
155188f1096SBen Tyner 
156188f1096SBen Tyner     // dbus specifics
157188f1096SBen Tyner     constexpr auto interface = "xyz.openbmc_project.Logging.Create";
158188f1096SBen Tyner     constexpr auto function  = "Create";
159188f1096SBen Tyner 
160188f1096SBen Tyner     sdbusplus::message::message method;
161188f1096SBen Tyner 
162188f1096SBen Tyner     if (0 == dbusMethod(pathLogging, interface, function, method))
163188f1096SBen Tyner     {
164188f1096SBen Tyner         try
165188f1096SBen Tyner         {
166188f1096SBen Tyner             // append additional dbus call parameters
167188f1096SBen Tyner             method.append(eventPelTerminate, levelPelError, additional);
168188f1096SBen Tyner 
169188f1096SBen Tyner             // using system dbus, no reply
170188f1096SBen Tyner             auto bus = sdbusplus::bus::new_system();
171188f1096SBen Tyner             bus.call_noreply(method);
172188f1096SBen Tyner         }
173188f1096SBen Tyner         catch (const sdbusplus::exception::SdBusError& e)
174188f1096SBen Tyner         {
175*6764d70eSBen Tyner             trace<level::INFO>("createPelRaw exception");
176*6764d70eSBen Tyner             std::string traceMsg = std::string(e.what(), maxTraceLen);
177*6764d70eSBen Tyner             trace<level::ERROR>(traceMsg.c_str());
178188f1096SBen Tyner         }
179188f1096SBen Tyner     }
180188f1096SBen Tyner }
181188f1096SBen Tyner 
182188f1096SBen Tyner /** @brief Get file descriptor of exisitng PEL */
183188f1096SBen Tyner int getPel(const uint32_t i_pelId)
184188f1096SBen Tyner {
185188f1096SBen Tyner     // GetPEL returns file descriptor (int)
186188f1096SBen Tyner     int fd = -1;
187188f1096SBen Tyner 
188188f1096SBen Tyner     // dbus specifics
189188f1096SBen Tyner     constexpr auto interface = "org.open_power.Logging.PEL";
190188f1096SBen Tyner     constexpr auto function  = "GetPEL";
191188f1096SBen Tyner 
192188f1096SBen Tyner     sdbusplus::message::message method;
193188f1096SBen Tyner 
194188f1096SBen Tyner     if (0 == dbusMethod(pathLogging, interface, function, method))
195188f1096SBen Tyner     {
196188f1096SBen Tyner         try
197188f1096SBen Tyner         {
198188f1096SBen Tyner             // additional dbus call parameters
199188f1096SBen Tyner             method.append(i_pelId);
200188f1096SBen Tyner 
201188f1096SBen Tyner             // using system dbus
202188f1096SBen Tyner             auto bus      = sdbusplus::bus::new_system();
203188f1096SBen Tyner             auto response = bus.call(method);
204188f1096SBen Tyner 
205188f1096SBen Tyner             // reply will be a unix file descriptor
206188f1096SBen Tyner             sdbusplus::message::unix_fd reply;
207188f1096SBen Tyner 
208188f1096SBen Tyner             // parse dbus reply
209188f1096SBen Tyner             response.read(reply);
210188f1096SBen Tyner 
211188f1096SBen Tyner             fd = dup(reply); // need to copy (dup) the file descriptor
212188f1096SBen Tyner         }
213188f1096SBen Tyner         catch (const sdbusplus::exception::SdBusError& e)
214188f1096SBen Tyner         {
215*6764d70eSBen Tyner             trace<level::INFO>("getPel exception");
216*6764d70eSBen Tyner             std::string traceMsg = std::string(e.what(), maxTraceLen);
217*6764d70eSBen Tyner             trace<level::ERROR>(traceMsg.c_str());
218188f1096SBen Tyner         }
219188f1096SBen Tyner     }
220188f1096SBen Tyner 
221188f1096SBen Tyner     return fd; // file descriptor or -1
222188f1096SBen Tyner }
223188f1096SBen Tyner 
224188f1096SBen Tyner } // namespace attn
225