1 #include "utils.hpp"
2 
3 #include <gpiod.h>
4 
5 #include <phosphor-logging/lg2.hpp>
6 
7 namespace phosphor
8 {
9 namespace state
10 {
11 namespace manager
12 {
13 namespace utils
14 {
15 
16 PHOSPHOR_LOG2_USING;
17 
18 constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper";
19 constexpr auto MAPPER_PATH = "/xyz/openbmc_project/object_mapper";
20 constexpr auto MAPPER_INTERFACE = "xyz.openbmc_project.ObjectMapper";
21 constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
22 
23 std::string getService(sdbusplus::bus::bus& bus, std::string path,
24                        std::string interface)
25 {
26     auto mapper = bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH,
27                                       MAPPER_INTERFACE, "GetObject");
28 
29     mapper.append(path, std::vector<std::string>({interface}));
30 
31     std::vector<std::pair<std::string, std::vector<std::string>>>
32         mapperResponse;
33 
34     try
35     {
36         auto mapperResponseMsg = bus.call(mapper);
37 
38         mapperResponseMsg.read(mapperResponse);
39         if (mapperResponse.empty())
40         {
41             error(
42                 "Error no matching service with path {PATH} and interface {INTERFACE}",
43                 "PATH", path, "INTERFACE", interface);
44             throw std::runtime_error("Error no matching service");
45         }
46     }
47     catch (const sdbusplus::exception::exception& e)
48     {
49         error("Error in mapper call with path {PATH}, interface "
50               "{INTERFACE}, and exception {ERROR}",
51               "PATH", path, "INTERFACE", interface, "ERROR", e);
52         throw;
53     }
54 
55     return mapperResponse.begin()->first;
56 }
57 
58 std::string getProperty(sdbusplus::bus::bus& bus, const std::string& path,
59                         const std::string& interface,
60                         const std::string& propertyName)
61 {
62     std::variant<std::string> property;
63     std::string service = getService(bus, path, interface);
64 
65     auto method = bus.new_method_call(service.c_str(), path.c_str(),
66                                       PROPERTY_INTERFACE, "Get");
67 
68     method.append(interface, propertyName);
69 
70     try
71     {
72         auto reply = bus.call(method);
73         reply.read(property);
74     }
75     catch (const sdbusplus::exception::exception& e)
76     {
77         error("Error in property Get, error {ERROR}, property {PROPERTY}",
78               "ERROR", e, "PROPERTY", propertyName);
79         throw;
80     }
81 
82     if (std::get<std::string>(property).empty())
83     {
84         error("Error reading property response for {PROPERTY}", "PROPERTY",
85               propertyName);
86         throw std::runtime_error("Error reading property response");
87     }
88 
89     return std::get<std::string>(property);
90 }
91 
92 void setProperty(sdbusplus::bus::bus& bus, const std::string& path,
93                  const std::string& interface, const std::string& property,
94                  const std::string& value)
95 {
96     std::variant<std::string> variantValue = value;
97     std::string service = getService(bus, path, interface);
98 
99     auto method = bus.new_method_call(service.c_str(), path.c_str(),
100                                       PROPERTY_INTERFACE, "Set");
101 
102     method.append(interface, property, variantValue);
103     bus.call_noreply(method);
104 
105     return;
106 }
107 
108 int getGpioValue(const std::string& gpioName)
109 {
110 
111     int gpioval = -1;
112     gpiod_line* line = gpiod_line_find(gpioName.c_str());
113 
114     if (nullptr != line)
115     {
116         // take ownership of gpio
117         if (0 != gpiod_line_request_input(line, "state-manager"))
118         {
119             error("Failed request for {GPIO_NAME} GPIO", "GPIO_NAME", gpioName);
120         }
121         else
122         {
123             // get gpio value
124             gpioval = gpiod_line_get_value(line);
125 
126             // release ownership of gpio
127             gpiod_line_close_chip(line);
128         }
129     }
130     return gpioval;
131 }
132 
133 void createError(
134     sdbusplus::bus::bus& bus, const std::string& errorMsg,
135     sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level errLevel,
136     std::map<std::string, std::string> additionalData)
137 {
138 
139     try
140     {
141         // Always add the _PID on for some extra logging debug
142         additionalData.emplace("_PID", std::to_string(getpid()));
143 
144         auto method = bus.new_method_call(
145             "xyz.openbmc_project.Logging", "/xyz/openbmc_project/logging",
146             "xyz.openbmc_project.Logging.Create", "Create");
147 
148         method.append(errorMsg, errLevel, additionalData);
149         auto resp = bus.call(method);
150     }
151     catch (const sdbusplus::exception::exception& e)
152     {
153         error("sdbusplus D-Bus call exception, error {ERROR} trying to create "
154               "an error with {ERROR_MSG}",
155               "ERROR", e, "ERROR_MSG", errorMsg);
156 
157         throw std::runtime_error(
158             "Error in invoking D-Bus logging create interface");
159     }
160     catch (const std::exception& e)
161     {
162         error("D-bus call exception: {ERROR}", "ERROR", e);
163         throw e;
164     }
165 }
166 
167 void createBmcDump(sdbusplus::bus::bus& bus)
168 {
169     auto method = bus.new_method_call(
170         "xyz.openbmc_project.Dump.Manager", "/xyz/openbmc_project/dump/bmc",
171         "xyz.openbmc_project.Dump.Create", "CreateDump");
172     method.append(
173         std::vector<
174             std::pair<std::string, std::variant<std::string, uint64_t>>>());
175     try
176     {
177         bus.call_noreply(method);
178     }
179     catch (const sdbusplus::exception::exception& e)
180     {
181         error("Failed to create BMC dump, exception:{ERROR}", "ERROR", e);
182         // just continue, this is error path anyway so we're just collecting
183         // what we can
184     }
185 }
186 
187 } // namespace utils
188 } // namespace manager
189 } // namespace state
190 } // namespace phosphor
191