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