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