1 #include <unistd.h>
2 
3 #include <phosphor-logging/lg2.hpp>
4 #include <watchdog_dbus.hpp>
5 #include <watchdog_logging.hpp>
6 
7 #include <string>
8 #include <vector>
9 
10 namespace watchdog
11 {
12 namespace dump
13 {
14 
15 int dbusMethod(const std::string& path, const std::string& interface,
16                const std::string& function, sdbusplus::message_t& method,
17                const std::string& extended)
18 {
19     int rc = RC_DBUS_ERROR; // assume error
20 
21     try
22     {
23         constexpr auto serviceFind = "xyz.openbmc_project.ObjectMapper";
24         constexpr auto pathFind = "/xyz/openbmc_project/object_mapper";
25         constexpr auto interfaceFind = "xyz.openbmc_project.ObjectMapper";
26         constexpr auto functionFind = "GetObject";
27 
28         auto bus = sdbusplus::bus::new_system(); // using system dbus
29 
30         // method to find service from object path and object interface
31         auto newMethod = bus.new_method_call(serviceFind, pathFind,
32                                              interfaceFind, functionFind);
33 
34         // find the service for specified object path and interface
35         newMethod.append(path.c_str());
36         newMethod.append(std::vector<std::string>({interface}));
37         auto reply = bus.call(newMethod);
38 
39         // dbus call results
40         std::map<std::string, std::vector<std::string>> responseFindService;
41         reply.read(responseFindService);
42 
43         // If we successfully found the service associated with the dbus object
44         // path and interface then create a method for the specified interface
45         // and function.
46         if (!responseFindService.empty())
47         {
48             auto service = responseFindService.begin()->first;
49 
50             // Some methods (e.g. get attribute) take an extended parameter
51             if (extended == "")
52             {
53                 // return the method
54                 method =
55                     bus.new_method_call(service.c_str(), path.c_str(),
56                                         interface.c_str(), function.c_str());
57             }
58             else
59             {
60                 // return extended method
61                 method =
62                     bus.new_method_call(service.c_str(), path.c_str(),
63                                         extended.c_str(), function.c_str());
64             }
65 
66             rc = RC_SUCCESS;
67         }
68         else
69         {
70             // This trace will be picked up in event log
71             lg2::info("dbusMethod service not found");
72             std::string traceMsgPath = std::string(path, maxTraceLen);
73             lg2::info(traceMsgPath.c_str());
74             std::string traceMsgIface = std::string(interface, maxTraceLen);
75             lg2::info(traceMsgIface.c_str());
76         }
77     }
78     catch (const sdbusplus::exception_t& e)
79     {
80         lg2::error("Error in dbusMethod ({ERROR})", "ERROR", e);
81     }
82 
83     return rc;
84 }
85 
86 uint32_t createPel(const std::string& eventType,
87                    std::map<std::string, std::string>& additional,
88                    const std::vector<FFDCTuple>& ffdc)
89 {
90     // Create returns plid
91     int plid = 0;
92 
93     // Need to provide pid when using create or create-with-ffdc methods
94     additional.emplace("_PID", std::to_string(getpid()));
95 
96     // Sdbus call specifics
97     constexpr auto interface = "org.open_power.Logging.PEL";
98     constexpr auto function = "CreatePELWithFFDCFiles";
99 
100     sdbusplus::message_t method;
101 
102     if (0 == dbusMethod(pathLogging, interface, function, method))
103     {
104         try
105         {
106             // append additional dbus call parameters
107             method.append(eventType, levelPelError, additional, ffdc);
108 
109             // using system dbus
110             auto bus = sdbusplus::bus::new_system();
111             auto response = bus.call(method);
112 
113             // reply will be tuple containing bmc log id, platform log id
114             std::tuple<uint32_t, uint32_t> reply = {0, 0};
115 
116             // parse dbus response into reply
117             response.read(reply);
118             plid = std::get<1>(reply); // platform log id is tuple "second"
119         }
120         catch (const sdbusplus::exception_t& e)
121         {
122             lg2::error("Error in createPel CreatePELWithFFDCFiles ({ERROR})",
123                        "ERROR", e);
124         }
125     }
126 
127     return plid; // platform log id or 0
128 }
129 
130 bool isHostStateRunning()
131 {
132     constexpr auto path = "/xyz/openbmc_project/state/host0";
133     constexpr auto interface = "xyz.openbmc_project.State.Host";
134     constexpr auto extended = "org.freedesktop.DBus.Properties";
135     constexpr auto function = "Get";
136 
137     sdbusplus::message_t method;
138 
139     if (0 == dbusMethod(path, interface, function, method, extended))
140     {
141         try
142         {
143             method.append(interface, "CurrentHostState");
144             auto bus = sdbusplus::bus::new_system();
145             auto response = bus.call(method);
146             std::variant<std::string> reply;
147 
148             response.read(reply);
149             std::string currentHostState(std::get<std::string>(reply));
150 
151             if (currentHostState ==
152                 "xyz.openbmc_project.State.Host.HostState.Running")
153             {
154                 return true;
155             }
156         }
157         catch (const sdbusplus::exception_t& e)
158         {
159             lg2::error("Failed to read CurrentHostState property ({ERROR})",
160                        "ERROR", e);
161         }
162     }
163 
164     return false;
165 }
166 
167 } // namespace dump
168 } // namespace watchdog
169