blob: 95760cbb1fade87ca0d1388e4047d0f14c281cff [file] [log] [blame]
NodeMan9727d1e142022-07-27 15:10:07 -05001#include "config.h"
2
Carol Wangdc059392020-03-13 17:39:17 +08003#include "utils.hpp"
4
NodeMan9727d1e142022-07-27 15:10:07 -05005#include <fmt/format.h>
6#include <fmt/printf.h>
Andrew Geisslerf8ae6a02022-01-21 17:00:20 -06007#include <gpiod.h>
8
Andrew Geissler8ffdb262021-09-20 15:25:19 -05009#include <phosphor-logging/lg2.hpp>
Carol Wangdc059392020-03-13 17:39:17 +080010
Andrew Geissler48a4e5e2023-02-15 18:23:34 -060011#include <chrono>
NodeMan9727d1e142022-07-27 15:10:07 -050012#include <filesystem>
13
Carol Wangdc059392020-03-13 17:39:17 +080014namespace phosphor
15{
16namespace state
17{
18namespace manager
19{
20namespace utils
21{
22
Andrew Geissler48a4e5e2023-02-15 18:23:34 -060023using namespace std::literals::chrono_literals;
24
Andrew Geissler8ffdb262021-09-20 15:25:19 -050025PHOSPHOR_LOG2_USING;
Carol Wangdc059392020-03-13 17:39:17 +080026
Andrew Geissler928bbf12023-02-14 13:30:14 -060027constexpr auto SYSTEMD_SERVICE = "org.freedesktop.systemd1";
28constexpr auto SYSTEMD_OBJ_PATH = "/org/freedesktop/systemd1";
29constexpr auto SYSTEMD_INTERFACE = "org.freedesktop.systemd1.Manager";
30
Carol Wangdc059392020-03-13 17:39:17 +080031constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper";
32constexpr auto MAPPER_PATH = "/xyz/openbmc_project/object_mapper";
33constexpr auto MAPPER_INTERFACE = "xyz.openbmc_project.ObjectMapper";
34constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
35
Patrick Williams5c4a0822023-02-28 02:40:35 -060036void subscribeToSystemdSignals(sdbusplus::bus_t& bus)
Andrew Geissler928bbf12023-02-14 13:30:14 -060037{
38 auto method = bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_OBJ_PATH,
39 SYSTEMD_INTERFACE, "Subscribe");
40
41 try
42 {
Andrew Geissler48a4e5e2023-02-15 18:23:34 -060043 // On OpenBMC based systems, systemd has had a few situations where it
44 // has been unable to respond to this call within the default d-bus
45 // timeout of 25 seconds. This is due to the large amount of work being
46 // done by systemd during OpenBMC startup. Set the timeout for this call
47 // to 60 seconds (worst case seen was around 30s so double it).
48 bus.call(method, 60s);
Andrew Geissler928bbf12023-02-14 13:30:14 -060049 }
50 catch (const sdbusplus::exception_t& e)
51 {
52 error("Failed to subscribe to systemd signals: {ERROR}", "ERROR", e);
53 throw std::runtime_error("Unable to subscribe to systemd signals");
54 }
55 return;
56}
57
Patrick Williams5c4a0822023-02-28 02:40:35 -060058std::string getService(sdbusplus::bus_t& bus, std::string path,
Carol Wangdc059392020-03-13 17:39:17 +080059 std::string interface)
60{
61 auto mapper = bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH,
62 MAPPER_INTERFACE, "GetObject");
63
64 mapper.append(path, std::vector<std::string>({interface}));
65
66 std::vector<std::pair<std::string, std::vector<std::string>>>
67 mapperResponse;
68
69 try
70 {
71 auto mapperResponseMsg = bus.call(mapper);
72
73 mapperResponseMsg.read(mapperResponse);
74 if (mapperResponse.empty())
75 {
Andrew Geisslerad65b2d2021-09-21 12:53:29 -050076 error(
77 "Error no matching service with path {PATH} and interface {INTERFACE}",
78 "PATH", path, "INTERFACE", interface);
Carol Wangdc059392020-03-13 17:39:17 +080079 throw std::runtime_error("Error no matching service");
80 }
81 }
Patrick Williamsf053e6f2022-07-22 19:26:54 -050082 catch (const sdbusplus::exception_t& e)
Carol Wangdc059392020-03-13 17:39:17 +080083 {
Andrew Geissler8ffdb262021-09-20 15:25:19 -050084 error("Error in mapper call with path {PATH}, interface "
85 "{INTERFACE}, and exception {ERROR}",
86 "PATH", path, "INTERFACE", interface, "ERROR", e);
Carol Wangdc059392020-03-13 17:39:17 +080087 throw;
88 }
89
90 return mapperResponse.begin()->first;
91}
92
Patrick Williamsf053e6f2022-07-22 19:26:54 -050093std::string getProperty(sdbusplus::bus_t& bus, const std::string& path,
Andrew Geissler49e67132022-01-26 14:27:52 -060094 const std::string& interface,
95 const std::string& propertyName)
96{
97 std::variant<std::string> property;
98 std::string service = getService(bus, path, interface);
99
100 auto method = bus.new_method_call(service.c_str(), path.c_str(),
101 PROPERTY_INTERFACE, "Get");
102
103 method.append(interface, propertyName);
104
105 try
106 {
107 auto reply = bus.call(method);
108 reply.read(property);
109 }
Patrick Williamsf053e6f2022-07-22 19:26:54 -0500110 catch (const sdbusplus::exception_t& e)
Andrew Geissler49e67132022-01-26 14:27:52 -0600111 {
112 error("Error in property Get, error {ERROR}, property {PROPERTY}",
113 "ERROR", e, "PROPERTY", propertyName);
114 throw;
115 }
116
117 if (std::get<std::string>(property).empty())
118 {
119 error("Error reading property response for {PROPERTY}", "PROPERTY",
120 propertyName);
121 throw std::runtime_error("Error reading property response");
122 }
123
124 return std::get<std::string>(property);
125}
126
Patrick Williamsf053e6f2022-07-22 19:26:54 -0500127void setProperty(sdbusplus::bus_t& bus, const std::string& path,
Carol Wangdc059392020-03-13 17:39:17 +0800128 const std::string& interface, const std::string& property,
129 const std::string& value)
130{
Patrick Williams2975e262020-05-13 18:01:09 -0500131 std::variant<std::string> variantValue = value;
Carol Wangdc059392020-03-13 17:39:17 +0800132 std::string service = getService(bus, path, interface);
133
134 auto method = bus.new_method_call(service.c_str(), path.c_str(),
135 PROPERTY_INTERFACE, "Set");
136
137 method.append(interface, property, variantValue);
138 bus.call_noreply(method);
139
140 return;
141}
142
Andrew Geisslerf8ae6a02022-01-21 17:00:20 -0600143int getGpioValue(const std::string& gpioName)
144{
Andrew Geisslerf8ae6a02022-01-21 17:00:20 -0600145 int gpioval = -1;
146 gpiod_line* line = gpiod_line_find(gpioName.c_str());
147
148 if (nullptr != line)
149 {
150 // take ownership of gpio
151 if (0 != gpiod_line_request_input(line, "state-manager"))
152 {
153 error("Failed request for {GPIO_NAME} GPIO", "GPIO_NAME", gpioName);
154 }
155 else
156 {
157 // get gpio value
158 gpioval = gpiod_line_get_value(line);
159
160 // release ownership of gpio
161 gpiod_line_close_chip(line);
162 }
163 }
164 return gpioval;
165}
166
Andrew Geissler9d4d0c92022-01-26 13:18:12 -0600167void createError(
Patrick Williamsf053e6f2022-07-22 19:26:54 -0500168 sdbusplus::bus_t& bus, const std::string& errorMsg,
Patrick Williams7e969cb2023-08-23 16:24:23 -0500169 sdbusplus::server::xyz::openbmc_project::logging::Entry::Level errLevel,
Andrew Geisslerd49f51e2022-03-07 14:57:07 -0600170 std::map<std::string, std::string> additionalData)
Andrew Geissler9d4d0c92022-01-26 13:18:12 -0600171{
Andrew Geissler9d4d0c92022-01-26 13:18:12 -0600172 try
173 {
Andrew Geisslerd49f51e2022-03-07 14:57:07 -0600174 // Always add the _PID on for some extra logging debug
Andrew Geissler9d4d0c92022-01-26 13:18:12 -0600175 additionalData.emplace("_PID", std::to_string(getpid()));
176
177 auto method = bus.new_method_call(
178 "xyz.openbmc_project.Logging", "/xyz/openbmc_project/logging",
179 "xyz.openbmc_project.Logging.Create", "Create");
180
181 method.append(errorMsg, errLevel, additionalData);
182 auto resp = bus.call(method);
183 }
Patrick Williamsf053e6f2022-07-22 19:26:54 -0500184 catch (const sdbusplus::exception_t& e)
Andrew Geissler9d4d0c92022-01-26 13:18:12 -0600185 {
186 error("sdbusplus D-Bus call exception, error {ERROR} trying to create "
187 "an error with {ERROR_MSG}",
188 "ERROR", e, "ERROR_MSG", errorMsg);
189
190 throw std::runtime_error(
191 "Error in invoking D-Bus logging create interface");
192 }
193 catch (const std::exception& e)
194 {
195 error("D-bus call exception: {ERROR}", "ERROR", e);
196 throw e;
197 }
198}
199
Patrick Williamsf053e6f2022-07-22 19:26:54 -0500200void createBmcDump(sdbusplus::bus_t& bus)
Andrew Geissler55e96ac2022-04-19 11:44:53 -0400201{
202 auto method = bus.new_method_call(
203 "xyz.openbmc_project.Dump.Manager", "/xyz/openbmc_project/dump/bmc",
204 "xyz.openbmc_project.Dump.Create", "CreateDump");
205 method.append(
206 std::vector<
207 std::pair<std::string, std::variant<std::string, uint64_t>>>());
208 try
209 {
210 bus.call_noreply(method);
211 }
Patrick Williamsf053e6f2022-07-22 19:26:54 -0500212 catch (const sdbusplus::exception_t& e)
Andrew Geissler55e96ac2022-04-19 11:44:53 -0400213 {
214 error("Failed to create BMC dump, exception:{ERROR}", "ERROR", e);
215 // just continue, this is error path anyway so we're just collecting
216 // what we can
217 }
218}
219
NodeMan9727d1e142022-07-27 15:10:07 -0500220bool checkACLoss(size_t& chassisId)
221{
Patrick Williams9e5cd382023-05-10 07:50:38 -0500222 std::string chassisLostPowerFileFmt = fmt::sprintf(CHASSIS_LOST_POWER_FILE,
223 chassisId);
NodeMan9727d1e142022-07-27 15:10:07 -0500224
225 std::filesystem::path chassisPowerLossFile{chassisLostPowerFileFmt};
226 if (std::filesystem::exists(chassisPowerLossFile))
227 {
228 return true;
229 }
230
231 return false;
232}
233
Andrew Geisslerfc1020f2023-05-24 17:07:38 -0400234bool isBmcReady(sdbusplus::bus_t& bus)
235{
236 auto bmcState = getProperty(bus, "/xyz/openbmc_project/state/bmc0",
237 "xyz.openbmc_project.State.BMC",
238 "CurrentBMCState");
239 if (bmcState != "xyz.openbmc_project.State.BMC.BMCState.Ready")
240 {
241 debug("BMC State is {BMC_STATE}", "BMC_STATE", bmcState);
242 return false;
243 }
244 return true;
245}
246
Potin Lai08865452023-11-07 23:28:11 +0800247bool waitBmcReady(sdbusplus::bus_t& bus, std::chrono::seconds timeout)
248{
249 while (timeout.count() != 0)
250 {
251 timeout--;
252 if (isBmcReady(bus))
253 {
254 return true;
255 }
256 std::this_thread::sleep_for(std::chrono::seconds(1));
257 }
258 return false;
259}
260
Carol Wangdc059392020-03-13 17:39:17 +0800261} // namespace utils
262} // namespace manager
263} // namespace state
264} // namespace phosphor