xref: /openbmc/openpower-hw-diags/attn/attn_dbus.cpp (revision 4bbcb38f367e58b3724768ad998e31610b38869a)
1*4bbcb38fSBen Tyner #include <attn_dbus.hpp>
2*4bbcb38fSBen Tyner #include <attn_handler.hpp>
3188f1096SBen Tyner #include <attn_logging.hpp>
4*4bbcb38fSBen Tyner #include <xyz/openbmc_project/State/Boot/Progress/server.hpp>
5188f1096SBen Tyner 
6188f1096SBen Tyner #include <string>
7188f1096SBen Tyner #include <vector>
8188f1096SBen Tyner 
9188f1096SBen Tyner namespace attn
10188f1096SBen Tyner {
11188f1096SBen Tyner 
12188f1096SBen Tyner /**
13188f1096SBen Tyner  * Create a dbus method
14188f1096SBen Tyner  *
15188f1096SBen Tyner  * Find the dbus service associated with the dbus object path and create
16188f1096SBen Tyner  * a dbus method for calling the specified dbus interface and function.
17188f1096SBen Tyner  *
18188f1096SBen Tyner  * @param i_path - dbus object path
19188f1096SBen Tyner  * @param i_interface - dbus method interface
20188f1096SBen Tyner  * @param i_function - dbus interface function
21188f1096SBen Tyner  * @param o_method - method that is created
22*4bbcb38fSBen Tyner  * @param i_extended - optional for extended methods
23188f1096SBen Tyner  * @return non-zero if error
24188f1096SBen Tyner  *
25188f1096SBen Tyner  **/
26188f1096SBen Tyner int dbusMethod(const std::string& i_path, const std::string& i_interface,
27188f1096SBen Tyner                const std::string& i_function,
28*4bbcb38fSBen Tyner                sdbusplus::message::message& o_method,
29*4bbcb38fSBen Tyner                const std::string& i_extended = "")
30188f1096SBen Tyner {
31*4bbcb38fSBen Tyner     int rc = RC_DBUS_ERROR; // assume error
32188f1096SBen Tyner 
33188f1096SBen Tyner     try
34188f1096SBen Tyner     {
35188f1096SBen Tyner         constexpr auto serviceFind   = "xyz.openbmc_project.ObjectMapper";
36188f1096SBen Tyner         constexpr auto pathFind      = "/xyz/openbmc_project/object_mapper";
37188f1096SBen Tyner         constexpr auto interfaceFind = "xyz.openbmc_project.ObjectMapper";
38188f1096SBen Tyner         constexpr auto functionFind  = "GetObject";
39188f1096SBen Tyner 
40188f1096SBen Tyner         auto bus = sdbusplus::bus::new_system(); // using system dbus
41188f1096SBen Tyner 
42188f1096SBen Tyner         // method to find service from object path and object interface
43188f1096SBen Tyner         auto method = bus.new_method_call(serviceFind, pathFind, interfaceFind,
44188f1096SBen Tyner                                           functionFind);
45188f1096SBen Tyner 
46188f1096SBen Tyner         // find the service for specified object path and interface
47188f1096SBen Tyner         method.append(i_path.c_str());
48188f1096SBen Tyner         method.append(std::vector<std::string>({i_interface}));
49188f1096SBen Tyner         auto reply = bus.call(method);
50188f1096SBen Tyner 
51188f1096SBen Tyner         // dbus call results
52188f1096SBen Tyner         std::map<std::string, std::vector<std::string>> responseFindService;
53188f1096SBen Tyner         reply.read(responseFindService);
54188f1096SBen Tyner 
55188f1096SBen Tyner         // If we successfully found the service associated with the dbus object
56188f1096SBen Tyner         // path and interface then create a method for the specified interface
57188f1096SBen Tyner         // and function.
58188f1096SBen Tyner         if (!responseFindService.empty())
59188f1096SBen Tyner         {
60188f1096SBen Tyner             auto service = responseFindService.begin()->first;
61188f1096SBen Tyner 
62*4bbcb38fSBen Tyner             // Some methods (e.g. get attribute) take an extended parameter
63*4bbcb38fSBen Tyner             if (i_extended == "")
64*4bbcb38fSBen Tyner             {
65188f1096SBen Tyner                 // return the method
66*4bbcb38fSBen Tyner                 o_method = bus.new_method_call(service.c_str(), i_path.c_str(),
67*4bbcb38fSBen Tyner                                                i_interface.c_str(),
68*4bbcb38fSBen Tyner                                                i_function.c_str());
69*4bbcb38fSBen Tyner             }
70*4bbcb38fSBen Tyner             else
71*4bbcb38fSBen Tyner             {
72*4bbcb38fSBen Tyner                 // return extended method
73188f1096SBen Tyner                 o_method =
74188f1096SBen Tyner                     bus.new_method_call(service.c_str(), i_path.c_str(),
75*4bbcb38fSBen Tyner                                         i_extended.c_str(), i_function.c_str());
76*4bbcb38fSBen Tyner             }
77188f1096SBen Tyner 
78*4bbcb38fSBen Tyner             rc = RC_SUCCESS;
79188f1096SBen Tyner         }
80188f1096SBen Tyner         else
81188f1096SBen Tyner         {
826764d70eSBen Tyner             // This trace will be picked up in event log
836764d70eSBen Tyner             trace<level::INFO>("dbusMethod service not found");
846764d70eSBen Tyner             std::string traceMsgPath = std::string(i_path, maxTraceLen);
856764d70eSBen Tyner             trace<level::INFO>(traceMsgPath.c_str());
866764d70eSBen Tyner             std::string traceMsgIface = std::string(i_interface, maxTraceLen);
876764d70eSBen Tyner             trace<level::INFO>(traceMsgIface.c_str());
88188f1096SBen Tyner         }
89188f1096SBen Tyner     }
90188f1096SBen Tyner     catch (const sdbusplus::exception::SdBusError& e)
91188f1096SBen Tyner     {
926764d70eSBen Tyner         trace<level::INFO>("dbusMethod exception");
936764d70eSBen Tyner         std::string traceMsg = std::string(e.what(), maxTraceLen);
946764d70eSBen Tyner         trace<level::ERROR>(traceMsg.c_str());
95188f1096SBen Tyner     }
96188f1096SBen Tyner 
97188f1096SBen Tyner     return rc;
98188f1096SBen Tyner }
99188f1096SBen Tyner 
100188f1096SBen Tyner /** @brief Create a PEL for the specified event type */
101188f1096SBen Tyner uint32_t createPel(const std::string& i_event,
102188f1096SBen Tyner                    std::map<std::string, std::string>& i_additional,
103188f1096SBen Tyner                    const std::vector<util::FFDCTuple>& i_ffdc)
104188f1096SBen Tyner {
105188f1096SBen Tyner     // CreatePELWithFFDCFiles returns plid
106188f1096SBen Tyner     int plid = 0;
107188f1096SBen Tyner 
108188f1096SBen Tyner     // Need to provide pid when using create or create-with-ffdc methods
109188f1096SBen Tyner     i_additional.emplace("_PID", std::to_string(getpid()));
110188f1096SBen Tyner 
111188f1096SBen Tyner     // Sdbus call specifics
112188f1096SBen Tyner     constexpr auto interface = "org.open_power.Logging.PEL";
113188f1096SBen Tyner     constexpr auto function  = "CreatePELWithFFDCFiles";
114188f1096SBen Tyner 
115188f1096SBen Tyner     sdbusplus::message::message method;
116188f1096SBen Tyner 
117188f1096SBen Tyner     if (0 == dbusMethod(pathLogging, interface, function, method))
118188f1096SBen Tyner     {
119188f1096SBen Tyner         try
120188f1096SBen Tyner         {
121188f1096SBen Tyner             // append additional dbus call paramaters
122188f1096SBen Tyner             method.append(i_event, levelPelError, i_additional, i_ffdc);
123188f1096SBen Tyner 
124188f1096SBen Tyner             // using system dbus
125188f1096SBen Tyner             auto bus      = sdbusplus::bus::new_system();
126188f1096SBen Tyner             auto response = bus.call(method);
127188f1096SBen Tyner 
128188f1096SBen Tyner             // reply will be tuple containing bmc log id, platform log id
129188f1096SBen Tyner             std::tuple<uint32_t, uint32_t> reply = {0, 0};
130188f1096SBen Tyner 
131*4bbcb38fSBen Tyner             // parse dbus response into reply
132188f1096SBen Tyner             response.read(reply);
133188f1096SBen Tyner             plid = std::get<1>(reply); // platform log id is tuple "second"
134188f1096SBen Tyner         }
135188f1096SBen Tyner         catch (const sdbusplus::exception::SdBusError& e)
136188f1096SBen Tyner         {
1376764d70eSBen Tyner             trace<level::INFO>("createPel exception");
1386764d70eSBen Tyner             std::string traceMsg = std::string(e.what(), maxTraceLen);
1396764d70eSBen Tyner             trace<level::ERROR>(traceMsg.c_str());
140188f1096SBen Tyner         }
141188f1096SBen Tyner     }
142188f1096SBen Tyner 
143188f1096SBen Tyner     return plid; // platform log id or 0
144188f1096SBen Tyner }
145188f1096SBen Tyner 
146188f1096SBen Tyner /** @brief Create a PEL from raw PEL data */
147188f1096SBen Tyner void createPelRaw(const std::vector<uint8_t>& i_buffer)
148188f1096SBen Tyner {
149188f1096SBen Tyner     // Create FFDC file from buffer data
150188f1096SBen Tyner     util::FFDCFile pelFile{util::FFDCFormat::Text};
151188f1096SBen Tyner     auto fd = pelFile.getFileDescriptor();
152188f1096SBen Tyner 
153188f1096SBen Tyner     auto filePath = pelFile.getPath(); // path to ffdc file
154188f1096SBen Tyner 
155d700609cSBen Tyner     size_t numBytes = write(fd, i_buffer.data(), i_buffer.size());
156d700609cSBen Tyner     if (i_buffer.size() != numBytes)
157d700609cSBen Tyner     {
158d700609cSBen Tyner         std::stringstream traceMsg;
159d700609cSBen Tyner         traceMsg << filePath.c_str() << " only " << (int)numBytes << " of "
160d700609cSBen Tyner                  << (int)i_buffer.size() << " bytes written";
161d700609cSBen Tyner         auto strobj = traceMsg.str();
162d700609cSBen Tyner         trace<level::ERROR>(strobj.c_str());
163d700609cSBen Tyner     }
164d700609cSBen Tyner 
165d700609cSBen Tyner     lseek(fd, 0, SEEK_SET);
166d700609cSBen Tyner 
167188f1096SBen Tyner     // Additional data for log
168188f1096SBen Tyner     std::map<std::string, std::string> additional;
169188f1096SBen Tyner     additional.emplace("RAWPEL", filePath.string());
170188f1096SBen Tyner     additional.emplace("_PID", std::to_string(getpid()));
171188f1096SBen Tyner 
172188f1096SBen Tyner     // dbus specifics
173188f1096SBen Tyner     constexpr auto interface = "xyz.openbmc_project.Logging.Create";
174188f1096SBen Tyner     constexpr auto function  = "Create";
175188f1096SBen Tyner 
176188f1096SBen Tyner     sdbusplus::message::message method;
177188f1096SBen Tyner 
178188f1096SBen Tyner     if (0 == dbusMethod(pathLogging, interface, function, method))
179188f1096SBen Tyner     {
180188f1096SBen Tyner         try
181188f1096SBen Tyner         {
182188f1096SBen Tyner             // append additional dbus call parameters
183188f1096SBen Tyner             method.append(eventPelTerminate, levelPelError, additional);
184188f1096SBen Tyner 
185188f1096SBen Tyner             // using system dbus, no reply
186188f1096SBen Tyner             auto bus = sdbusplus::bus::new_system();
187188f1096SBen Tyner             bus.call_noreply(method);
188188f1096SBen Tyner         }
189188f1096SBen Tyner         catch (const sdbusplus::exception::SdBusError& e)
190188f1096SBen Tyner         {
1916764d70eSBen Tyner             trace<level::INFO>("createPelRaw exception");
1926764d70eSBen Tyner             std::string traceMsg = std::string(e.what(), maxTraceLen);
1936764d70eSBen Tyner             trace<level::ERROR>(traceMsg.c_str());
194188f1096SBen Tyner         }
195188f1096SBen Tyner     }
196188f1096SBen Tyner }
197188f1096SBen Tyner 
198188f1096SBen Tyner /** @brief Get file descriptor of exisitng PEL */
199188f1096SBen Tyner int getPel(const uint32_t i_pelId)
200188f1096SBen Tyner {
201188f1096SBen Tyner     // GetPEL returns file descriptor (int)
202188f1096SBen Tyner     int fd = -1;
203188f1096SBen Tyner 
204188f1096SBen Tyner     // dbus specifics
205188f1096SBen Tyner     constexpr auto interface = "org.open_power.Logging.PEL";
206188f1096SBen Tyner     constexpr auto function  = "GetPEL";
207188f1096SBen Tyner 
208188f1096SBen Tyner     sdbusplus::message::message method;
209188f1096SBen Tyner 
210188f1096SBen Tyner     if (0 == dbusMethod(pathLogging, interface, function, method))
211188f1096SBen Tyner     {
212188f1096SBen Tyner         try
213188f1096SBen Tyner         {
214188f1096SBen Tyner             // additional dbus call parameters
215188f1096SBen Tyner             method.append(i_pelId);
216188f1096SBen Tyner 
217188f1096SBen Tyner             // using system dbus
218188f1096SBen Tyner             auto bus      = sdbusplus::bus::new_system();
219188f1096SBen Tyner             auto response = bus.call(method);
220188f1096SBen Tyner 
221188f1096SBen Tyner             // reply will be a unix file descriptor
222188f1096SBen Tyner             sdbusplus::message::unix_fd reply;
223188f1096SBen Tyner 
224*4bbcb38fSBen Tyner             // parse dbus response into reply
225188f1096SBen Tyner             response.read(reply);
226188f1096SBen Tyner 
227188f1096SBen Tyner             fd = dup(reply); // need to copy (dup) the file descriptor
228188f1096SBen Tyner         }
229188f1096SBen Tyner         catch (const sdbusplus::exception::SdBusError& e)
230188f1096SBen Tyner         {
2316764d70eSBen Tyner             trace<level::INFO>("getPel exception");
2326764d70eSBen Tyner             std::string traceMsg = std::string(e.what(), maxTraceLen);
2336764d70eSBen Tyner             trace<level::ERROR>(traceMsg.c_str());
234188f1096SBen Tyner         }
235188f1096SBen Tyner     }
236188f1096SBen Tyner 
237188f1096SBen Tyner     return fd; // file descriptor or -1
238188f1096SBen Tyner }
239188f1096SBen Tyner 
240*4bbcb38fSBen Tyner /** @brief Get the running state of the host */
241*4bbcb38fSBen Tyner HostRunningState hostRunningState()
242*4bbcb38fSBen Tyner {
243*4bbcb38fSBen Tyner     HostRunningState host = HostRunningState::Unknown;
244*4bbcb38fSBen Tyner 
245*4bbcb38fSBen Tyner     // dbus specifics
246*4bbcb38fSBen Tyner     constexpr auto path      = "/xyz/openbmc_project/state/host0";
247*4bbcb38fSBen Tyner     constexpr auto interface = "xyz.openbmc_project.State.Boot.Progress";
248*4bbcb38fSBen Tyner     constexpr auto extended  = "org.freedesktop.DBus.Properties";
249*4bbcb38fSBen Tyner     constexpr auto function  = "Get";
250*4bbcb38fSBen Tyner 
251*4bbcb38fSBen Tyner     sdbusplus::message::message method;
252*4bbcb38fSBen Tyner 
253*4bbcb38fSBen Tyner     if (0 == dbusMethod(path, interface, function, method, extended))
254*4bbcb38fSBen Tyner     {
255*4bbcb38fSBen Tyner         try
256*4bbcb38fSBen Tyner         {
257*4bbcb38fSBen Tyner             // additional dbus call parameters
258*4bbcb38fSBen Tyner             method.append(interface, "BootProgress");
259*4bbcb38fSBen Tyner 
260*4bbcb38fSBen Tyner             // using system dbus
261*4bbcb38fSBen Tyner             auto bus      = sdbusplus::bus::new_system();
262*4bbcb38fSBen Tyner             auto response = bus.call(method);
263*4bbcb38fSBen Tyner 
264*4bbcb38fSBen Tyner             // reply will be a variant
265*4bbcb38fSBen Tyner             std::variant<std::string, bool, std::vector<uint8_t>,
266*4bbcb38fSBen Tyner                          std::vector<std::string>>
267*4bbcb38fSBen Tyner                 reply;
268*4bbcb38fSBen Tyner 
269*4bbcb38fSBen Tyner             // parse dbus response into reply
270*4bbcb38fSBen Tyner             response.read(reply);
271*4bbcb38fSBen Tyner 
272*4bbcb38fSBen Tyner             // get boot progress (string) and convert to boot stage
273*4bbcb38fSBen Tyner             std::string bootProgress(std::get<std::string>(reply));
274*4bbcb38fSBen Tyner 
275*4bbcb38fSBen Tyner             using BootProgress = sdbusplus::xyz::openbmc_project::State::Boot::
276*4bbcb38fSBen Tyner                 server::Progress::ProgressStages;
277*4bbcb38fSBen Tyner 
278*4bbcb38fSBen Tyner             BootProgress stage = sdbusplus::xyz::openbmc_project::State::Boot::
279*4bbcb38fSBen Tyner                 server::Progress::convertProgressStagesFromString(bootProgress);
280*4bbcb38fSBen Tyner 
281*4bbcb38fSBen Tyner             if ((stage == BootProgress::SystemInitComplete) ||
282*4bbcb38fSBen Tyner                 (stage == BootProgress::OSStart) ||
283*4bbcb38fSBen Tyner                 (stage == BootProgress::OSRunning))
284*4bbcb38fSBen Tyner             {
285*4bbcb38fSBen Tyner                 host = HostRunningState::Started;
286*4bbcb38fSBen Tyner             }
287*4bbcb38fSBen Tyner             else
288*4bbcb38fSBen Tyner             {
289*4bbcb38fSBen Tyner                 host = HostRunningState::NotStarted;
290*4bbcb38fSBen Tyner             }
291*4bbcb38fSBen Tyner         }
292*4bbcb38fSBen Tyner         catch (const sdbusplus::exception::SdBusError& e)
293*4bbcb38fSBen Tyner         {
294*4bbcb38fSBen Tyner             trace<level::INFO>("hostRunningState exception");
295*4bbcb38fSBen Tyner             std::string traceMsg = std::string(e.what(), maxTraceLen);
296*4bbcb38fSBen Tyner             trace<level::ERROR>(traceMsg.c_str());
297*4bbcb38fSBen Tyner         }
298*4bbcb38fSBen Tyner     }
299*4bbcb38fSBen Tyner 
300*4bbcb38fSBen Tyner     return host;
301*4bbcb38fSBen Tyner }
302188f1096SBen Tyner } // namespace attn
303