blob: 332ddc06cdc0cbfc816b1f012fb5bc1ba731f341 [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>
Patrick Williams9a286db2024-01-17 06:29:47 -060010#include <xyz/openbmc_project/Dump/Create/client.hpp>
11#include <xyz/openbmc_project/Logging/Create/client.hpp>
12#include <xyz/openbmc_project/ObjectMapper/client.hpp>
13#include <xyz/openbmc_project/State/BMC/client.hpp>
Carol Wangdc059392020-03-13 17:39:17 +080014
Andrew Geissler48a4e5e2023-02-15 18:23:34 -060015#include <chrono>
NodeMan9727d1e142022-07-27 15:10:07 -050016#include <filesystem>
17
Carol Wangdc059392020-03-13 17:39:17 +080018namespace phosphor
19{
20namespace state
21{
22namespace manager
23{
24namespace utils
25{
26
Andrew Geissler48a4e5e2023-02-15 18:23:34 -060027using namespace std::literals::chrono_literals;
28
Andrew Geissler8ffdb262021-09-20 15:25:19 -050029PHOSPHOR_LOG2_USING;
Carol Wangdc059392020-03-13 17:39:17 +080030
Andrew Geissler928bbf12023-02-14 13:30:14 -060031constexpr auto SYSTEMD_SERVICE = "org.freedesktop.systemd1";
32constexpr auto SYSTEMD_OBJ_PATH = "/org/freedesktop/systemd1";
33constexpr auto SYSTEMD_INTERFACE = "org.freedesktop.systemd1.Manager";
Carol Wangdc059392020-03-13 17:39:17 +080034constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
35
Patrick Williams9a286db2024-01-17 06:29:47 -060036using ObjectMapper = sdbusplus::client::xyz::openbmc_project::ObjectMapper<>;
37
Patrick Williams5c4a0822023-02-28 02:40:35 -060038void subscribeToSystemdSignals(sdbusplus::bus_t& bus)
Andrew Geissler928bbf12023-02-14 13:30:14 -060039{
40 auto method = bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_OBJ_PATH,
41 SYSTEMD_INTERFACE, "Subscribe");
42
43 try
44 {
Andrew Geissler48a4e5e2023-02-15 18:23:34 -060045 // On OpenBMC based systems, systemd has had a few situations where it
46 // has been unable to respond to this call within the default d-bus
47 // timeout of 25 seconds. This is due to the large amount of work being
48 // done by systemd during OpenBMC startup. Set the timeout for this call
49 // to 60 seconds (worst case seen was around 30s so double it).
50 bus.call(method, 60s);
Andrew Geissler928bbf12023-02-14 13:30:14 -060051 }
52 catch (const sdbusplus::exception_t& e)
53 {
54 error("Failed to subscribe to systemd signals: {ERROR}", "ERROR", e);
55 throw std::runtime_error("Unable to subscribe to systemd signals");
56 }
57 return;
58}
59
Patrick Williams5c4a0822023-02-28 02:40:35 -060060std::string getService(sdbusplus::bus_t& bus, std::string path,
Carol Wangdc059392020-03-13 17:39:17 +080061 std::string interface)
62{
Patrick Williams9a286db2024-01-17 06:29:47 -060063 auto mapper = bus.new_method_call(ObjectMapper::default_service,
64 ObjectMapper::instance_path,
65 ObjectMapper::interface, "GetObject");
Carol Wangdc059392020-03-13 17:39:17 +080066
67 mapper.append(path, std::vector<std::string>({interface}));
68
69 std::vector<std::pair<std::string, std::vector<std::string>>>
70 mapperResponse;
71
72 try
73 {
74 auto mapperResponseMsg = bus.call(mapper);
75
76 mapperResponseMsg.read(mapperResponse);
77 if (mapperResponse.empty())
78 {
Andrew Geisslerad65b2d2021-09-21 12:53:29 -050079 error(
80 "Error no matching service with path {PATH} and interface {INTERFACE}",
81 "PATH", path, "INTERFACE", interface);
Carol Wangdc059392020-03-13 17:39:17 +080082 throw std::runtime_error("Error no matching service");
83 }
84 }
Patrick Williamsf053e6f2022-07-22 19:26:54 -050085 catch (const sdbusplus::exception_t& e)
Carol Wangdc059392020-03-13 17:39:17 +080086 {
Andrew Geissler8ffdb262021-09-20 15:25:19 -050087 error("Error in mapper call with path {PATH}, interface "
88 "{INTERFACE}, and exception {ERROR}",
89 "PATH", path, "INTERFACE", interface, "ERROR", e);
Carol Wangdc059392020-03-13 17:39:17 +080090 throw;
91 }
92
93 return mapperResponse.begin()->first;
94}
95
Patrick Williamsf053e6f2022-07-22 19:26:54 -050096std::string getProperty(sdbusplus::bus_t& bus, const std::string& path,
Andrew Geissler49e67132022-01-26 14:27:52 -060097 const std::string& interface,
98 const std::string& propertyName)
99{
100 std::variant<std::string> property;
101 std::string service = getService(bus, path, interface);
102
103 auto method = bus.new_method_call(service.c_str(), path.c_str(),
104 PROPERTY_INTERFACE, "Get");
105
106 method.append(interface, propertyName);
107
108 try
109 {
110 auto reply = bus.call(method);
111 reply.read(property);
112 }
Patrick Williamsf053e6f2022-07-22 19:26:54 -0500113 catch (const sdbusplus::exception_t& e)
Andrew Geissler49e67132022-01-26 14:27:52 -0600114 {
115 error("Error in property Get, error {ERROR}, property {PROPERTY}",
116 "ERROR", e, "PROPERTY", propertyName);
117 throw;
118 }
119
120 if (std::get<std::string>(property).empty())
121 {
122 error("Error reading property response for {PROPERTY}", "PROPERTY",
123 propertyName);
124 throw std::runtime_error("Error reading property response");
125 }
126
127 return std::get<std::string>(property);
128}
129
Patrick Williamsf053e6f2022-07-22 19:26:54 -0500130void setProperty(sdbusplus::bus_t& bus, const std::string& path,
Carol Wangdc059392020-03-13 17:39:17 +0800131 const std::string& interface, const std::string& property,
132 const std::string& value)
133{
Patrick Williams2975e262020-05-13 18:01:09 -0500134 std::variant<std::string> variantValue = value;
Carol Wangdc059392020-03-13 17:39:17 +0800135 std::string service = getService(bus, path, interface);
136
137 auto method = bus.new_method_call(service.c_str(), path.c_str(),
138 PROPERTY_INTERFACE, "Set");
139
140 method.append(interface, property, variantValue);
141 bus.call_noreply(method);
142
143 return;
144}
145
Andrew Geisslerf8ae6a02022-01-21 17:00:20 -0600146int getGpioValue(const std::string& gpioName)
147{
Andrew Geisslerf8ae6a02022-01-21 17:00:20 -0600148 int gpioval = -1;
149 gpiod_line* line = gpiod_line_find(gpioName.c_str());
150
151 if (nullptr != line)
152 {
153 // take ownership of gpio
154 if (0 != gpiod_line_request_input(line, "state-manager"))
155 {
156 error("Failed request for {GPIO_NAME} GPIO", "GPIO_NAME", gpioName);
157 }
158 else
159 {
160 // get gpio value
161 gpioval = gpiod_line_get_value(line);
162
163 // release ownership of gpio
164 gpiod_line_close_chip(line);
165 }
166 }
167 return gpioval;
168}
169
Andrew Geissler9d4d0c92022-01-26 13:18:12 -0600170void createError(
Patrick Williamsf053e6f2022-07-22 19:26:54 -0500171 sdbusplus::bus_t& bus, const std::string& errorMsg,
Patrick Williams7e969cb2023-08-23 16:24:23 -0500172 sdbusplus::server::xyz::openbmc_project::logging::Entry::Level errLevel,
Andrew Geisslerd49f51e2022-03-07 14:57:07 -0600173 std::map<std::string, std::string> additionalData)
Andrew Geissler9d4d0c92022-01-26 13:18:12 -0600174{
Andrew Geissler9d4d0c92022-01-26 13:18:12 -0600175 try
176 {
Andrew Geisslerd49f51e2022-03-07 14:57:07 -0600177 // Always add the _PID on for some extra logging debug
Andrew Geissler9d4d0c92022-01-26 13:18:12 -0600178 additionalData.emplace("_PID", std::to_string(getpid()));
179
Patrick Williams9a286db2024-01-17 06:29:47 -0600180 using LoggingCreate =
181 sdbusplus::client::xyz::openbmc_project::logging::Create<>;
182
183 auto method = bus.new_method_call(LoggingCreate::default_service,
184 LoggingCreate::instance_path,
185 LoggingCreate::interface, "Create");
Andrew Geissler9d4d0c92022-01-26 13:18:12 -0600186
187 method.append(errorMsg, errLevel, additionalData);
188 auto resp = bus.call(method);
189 }
Patrick Williamsf053e6f2022-07-22 19:26:54 -0500190 catch (const sdbusplus::exception_t& e)
Andrew Geissler9d4d0c92022-01-26 13:18:12 -0600191 {
192 error("sdbusplus D-Bus call exception, error {ERROR} trying to create "
193 "an error with {ERROR_MSG}",
194 "ERROR", e, "ERROR_MSG", errorMsg);
195
196 throw std::runtime_error(
197 "Error in invoking D-Bus logging create interface");
198 }
199 catch (const std::exception& e)
200 {
201 error("D-bus call exception: {ERROR}", "ERROR", e);
202 throw e;
203 }
204}
205
Patrick Williamsf053e6f2022-07-22 19:26:54 -0500206void createBmcDump(sdbusplus::bus_t& bus)
Andrew Geissler55e96ac2022-04-19 11:44:53 -0400207{
Patrick Williams9a286db2024-01-17 06:29:47 -0600208 using DumpCreate = sdbusplus::client::xyz::openbmc_project::dump::Create<>;
209 auto dumpPath =
210 sdbusplus::message::object_path(DumpCreate::namespace_path::value) /
211 DumpCreate::namespace_path::bmc;
212
213 auto method = bus.new_method_call(DumpCreate::default_service,
214 dumpPath.str.c_str(),
215 DumpCreate::interface, "CreateDump");
Andrew Geissler55e96ac2022-04-19 11:44:53 -0400216 method.append(
217 std::vector<
218 std::pair<std::string, std::variant<std::string, uint64_t>>>());
219 try
220 {
221 bus.call_noreply(method);
222 }
Patrick Williamsf053e6f2022-07-22 19:26:54 -0500223 catch (const sdbusplus::exception_t& e)
Andrew Geissler55e96ac2022-04-19 11:44:53 -0400224 {
225 error("Failed to create BMC dump, exception:{ERROR}", "ERROR", e);
226 // just continue, this is error path anyway so we're just collecting
227 // what we can
228 }
229}
230
NodeMan9727d1e142022-07-27 15:10:07 -0500231bool checkACLoss(size_t& chassisId)
232{
Patrick Williams9e5cd382023-05-10 07:50:38 -0500233 std::string chassisLostPowerFileFmt = fmt::sprintf(CHASSIS_LOST_POWER_FILE,
234 chassisId);
NodeMan9727d1e142022-07-27 15:10:07 -0500235
236 std::filesystem::path chassisPowerLossFile{chassisLostPowerFileFmt};
237 if (std::filesystem::exists(chassisPowerLossFile))
238 {
239 return true;
240 }
241
242 return false;
243}
244
Andrew Geisslerfc1020f2023-05-24 17:07:38 -0400245bool isBmcReady(sdbusplus::bus_t& bus)
246{
Patrick Williams9a286db2024-01-17 06:29:47 -0600247 using BMC = sdbusplus::client::xyz::openbmc_project::state::BMC<>;
248 auto bmcPath = sdbusplus::message::object_path(BMC::namespace_path::value) /
249 BMC::namespace_path::bmc;
250
251 auto bmcState = getProperty(bus, bmcPath.str.c_str(), BMC::interface,
Andrew Geisslerfc1020f2023-05-24 17:07:38 -0400252 "CurrentBMCState");
Patrick Williams9a286db2024-01-17 06:29:47 -0600253
254 if (sdbusplus::message::convert_from_string<BMC::BMCState>(bmcState) !=
255 BMC::BMCState::Ready)
Andrew Geisslerfc1020f2023-05-24 17:07:38 -0400256 {
257 debug("BMC State is {BMC_STATE}", "BMC_STATE", bmcState);
258 return false;
259 }
260 return true;
261}
262
Potin Lai08865452023-11-07 23:28:11 +0800263bool waitBmcReady(sdbusplus::bus_t& bus, std::chrono::seconds timeout)
264{
265 while (timeout.count() != 0)
266 {
267 timeout--;
268 if (isBmcReady(bus))
269 {
270 return true;
271 }
272 std::this_thread::sleep_for(std::chrono::seconds(1));
273 }
274 return false;
275}
276
Carol Wangdc059392020-03-13 17:39:17 +0800277} // namespace utils
278} // namespace manager
279} // namespace state
280} // namespace phosphor