blob: 04ce3a4e959d71e4032f1800581abe160ffdf59c [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
Andrew Geisslerf8ae6a02022-01-21 17:00:20 -06005#include <gpiod.h>
6
Andrew Geissler8ffdb262021-09-20 15:25:19 -05007#include <phosphor-logging/lg2.hpp>
Patrick Williams9a286db2024-01-17 06:29:47 -06008#include <xyz/openbmc_project/Dump/Create/client.hpp>
9#include <xyz/openbmc_project/Logging/Create/client.hpp>
10#include <xyz/openbmc_project/ObjectMapper/client.hpp>
Thang Tran9f381522024-10-18 10:11:01 +070011#include <xyz/openbmc_project/Software/ActivationBlocksTransition/client.hpp>
Patrick Williams9a286db2024-01-17 06:29:47 -060012#include <xyz/openbmc_project/State/BMC/client.hpp>
Carol Wangdc059392020-03-13 17:39:17 +080013
Andrew Geissler48a4e5e2023-02-15 18:23:34 -060014#include <chrono>
NodeMan9727d1e142022-07-27 15:10:07 -050015#include <filesystem>
Patrick Williams78c066f2024-02-13 12:25:58 -060016#include <format>
NodeMan9727d1e142022-07-27 15:10:07 -050017
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<>;
Thang Tran9f381522024-10-18 10:11:01 +070037using ActBlockTrans = sdbusplus::client::xyz::openbmc_project::software::
38 ActivationBlocksTransition<>;
Patrick Williams9a286db2024-01-17 06:29:47 -060039
Patrick Williams5c4a0822023-02-28 02:40:35 -060040void subscribeToSystemdSignals(sdbusplus::bus_t& bus)
Andrew Geissler928bbf12023-02-14 13:30:14 -060041{
42 auto method = bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_OBJ_PATH,
43 SYSTEMD_INTERFACE, "Subscribe");
44
45 try
46 {
Andrew Geissler48a4e5e2023-02-15 18:23:34 -060047 // On OpenBMC based systems, systemd has had a few situations where it
48 // has been unable to respond to this call within the default d-bus
49 // timeout of 25 seconds. This is due to the large amount of work being
50 // done by systemd during OpenBMC startup. Set the timeout for this call
51 // to 60 seconds (worst case seen was around 30s so double it).
52 bus.call(method, 60s);
Andrew Geissler928bbf12023-02-14 13:30:14 -060053 }
54 catch (const sdbusplus::exception_t& e)
55 {
56 error("Failed to subscribe to systemd signals: {ERROR}", "ERROR", e);
57 throw std::runtime_error("Unable to subscribe to systemd signals");
58 }
59 return;
60}
61
Patrick Williams5c4a0822023-02-28 02:40:35 -060062std::string getService(sdbusplus::bus_t& bus, std::string path,
Carol Wangdc059392020-03-13 17:39:17 +080063 std::string interface)
64{
Patrick Williams9a286db2024-01-17 06:29:47 -060065 auto mapper = bus.new_method_call(ObjectMapper::default_service,
66 ObjectMapper::instance_path,
67 ObjectMapper::interface, "GetObject");
Carol Wangdc059392020-03-13 17:39:17 +080068
69 mapper.append(path, std::vector<std::string>({interface}));
70
71 std::vector<std::pair<std::string, std::vector<std::string>>>
72 mapperResponse;
73
74 try
75 {
76 auto mapperResponseMsg = bus.call(mapper);
77
78 mapperResponseMsg.read(mapperResponse);
79 if (mapperResponse.empty())
80 {
Andrew Geisslerad65b2d2021-09-21 12:53:29 -050081 error(
82 "Error no matching service with path {PATH} and interface {INTERFACE}",
83 "PATH", path, "INTERFACE", interface);
Carol Wangdc059392020-03-13 17:39:17 +080084 throw std::runtime_error("Error no matching service");
85 }
86 }
Patrick Williamsf053e6f2022-07-22 19:26:54 -050087 catch (const sdbusplus::exception_t& e)
Carol Wangdc059392020-03-13 17:39:17 +080088 {
Andrew Geissler8ffdb262021-09-20 15:25:19 -050089 error("Error in mapper call with path {PATH}, interface "
90 "{INTERFACE}, and exception {ERROR}",
91 "PATH", path, "INTERFACE", interface, "ERROR", e);
Carol Wangdc059392020-03-13 17:39:17 +080092 throw;
93 }
94
95 return mapperResponse.begin()->first;
96}
97
Patrick Williamsf053e6f2022-07-22 19:26:54 -050098std::string getProperty(sdbusplus::bus_t& bus, const std::string& path,
Andrew Geissler49e67132022-01-26 14:27:52 -060099 const std::string& interface,
100 const std::string& propertyName)
101{
102 std::variant<std::string> property;
103 std::string service = getService(bus, path, interface);
104
105 auto method = bus.new_method_call(service.c_str(), path.c_str(),
106 PROPERTY_INTERFACE, "Get");
107
108 method.append(interface, propertyName);
109
110 try
111 {
112 auto reply = bus.call(method);
113 reply.read(property);
114 }
Patrick Williamsf053e6f2022-07-22 19:26:54 -0500115 catch (const sdbusplus::exception_t& e)
Andrew Geissler49e67132022-01-26 14:27:52 -0600116 {
117 error("Error in property Get, error {ERROR}, property {PROPERTY}",
118 "ERROR", e, "PROPERTY", propertyName);
119 throw;
120 }
121
122 if (std::get<std::string>(property).empty())
123 {
124 error("Error reading property response for {PROPERTY}", "PROPERTY",
125 propertyName);
126 throw std::runtime_error("Error reading property response");
127 }
128
129 return std::get<std::string>(property);
130}
131
Patrick Williamsf053e6f2022-07-22 19:26:54 -0500132void setProperty(sdbusplus::bus_t& bus, const std::string& path,
Carol Wangdc059392020-03-13 17:39:17 +0800133 const std::string& interface, const std::string& property,
134 const std::string& value)
135{
Patrick Williams2975e262020-05-13 18:01:09 -0500136 std::variant<std::string> variantValue = value;
Carol Wangdc059392020-03-13 17:39:17 +0800137 std::string service = getService(bus, path, interface);
138
139 auto method = bus.new_method_call(service.c_str(), path.c_str(),
140 PROPERTY_INTERFACE, "Set");
141
142 method.append(interface, property, variantValue);
143 bus.call_noreply(method);
144
145 return;
146}
147
Andrew Geisslerf8ae6a02022-01-21 17:00:20 -0600148int getGpioValue(const std::string& gpioName)
149{
Andrew Geisslerf8ae6a02022-01-21 17:00:20 -0600150 int gpioval = -1;
151 gpiod_line* line = gpiod_line_find(gpioName.c_str());
152
153 if (nullptr != line)
154 {
155 // take ownership of gpio
156 if (0 != gpiod_line_request_input(line, "state-manager"))
157 {
158 error("Failed request for {GPIO_NAME} GPIO", "GPIO_NAME", gpioName);
159 }
160 else
161 {
162 // get gpio value
163 gpioval = gpiod_line_get_value(line);
164
165 // release ownership of gpio
166 gpiod_line_close_chip(line);
167 }
168 }
169 return gpioval;
170}
171
Andrew Geissler9d4d0c92022-01-26 13:18:12 -0600172void createError(
Patrick Williamsf053e6f2022-07-22 19:26:54 -0500173 sdbusplus::bus_t& bus, const std::string& errorMsg,
Patrick Williams7e969cb2023-08-23 16:24:23 -0500174 sdbusplus::server::xyz::openbmc_project::logging::Entry::Level errLevel,
Andrew Geisslerd49f51e2022-03-07 14:57:07 -0600175 std::map<std::string, std::string> additionalData)
Andrew Geissler9d4d0c92022-01-26 13:18:12 -0600176{
Andrew Geissler9d4d0c92022-01-26 13:18:12 -0600177 try
178 {
Andrew Geisslerd49f51e2022-03-07 14:57:07 -0600179 // Always add the _PID on for some extra logging debug
Andrew Geissler9d4d0c92022-01-26 13:18:12 -0600180 additionalData.emplace("_PID", std::to_string(getpid()));
181
Patrick Williams9a286db2024-01-17 06:29:47 -0600182 using LoggingCreate =
183 sdbusplus::client::xyz::openbmc_project::logging::Create<>;
184
185 auto method = bus.new_method_call(LoggingCreate::default_service,
186 LoggingCreate::instance_path,
187 LoggingCreate::interface, "Create");
Andrew Geissler9d4d0c92022-01-26 13:18:12 -0600188
189 method.append(errorMsg, errLevel, additionalData);
190 auto resp = bus.call(method);
191 }
Patrick Williamsf053e6f2022-07-22 19:26:54 -0500192 catch (const sdbusplus::exception_t& e)
Andrew Geissler9d4d0c92022-01-26 13:18:12 -0600193 {
194 error("sdbusplus D-Bus call exception, error {ERROR} trying to create "
195 "an error with {ERROR_MSG}",
196 "ERROR", e, "ERROR_MSG", errorMsg);
197
198 throw std::runtime_error(
199 "Error in invoking D-Bus logging create interface");
200 }
201 catch (const std::exception& e)
202 {
203 error("D-bus call exception: {ERROR}", "ERROR", e);
204 throw e;
205 }
206}
207
Patrick Williamsf053e6f2022-07-22 19:26:54 -0500208void createBmcDump(sdbusplus::bus_t& bus)
Andrew Geissler55e96ac2022-04-19 11:44:53 -0400209{
Patrick Williams9a286db2024-01-17 06:29:47 -0600210 using DumpCreate = sdbusplus::client::xyz::openbmc_project::dump::Create<>;
211 auto dumpPath =
212 sdbusplus::message::object_path(DumpCreate::namespace_path::value) /
213 DumpCreate::namespace_path::bmc;
214
Patrick Williams1b2c3c02024-08-16 15:20:29 -0400215 auto method =
216 bus.new_method_call(DumpCreate::default_service, dumpPath.str.c_str(),
217 DumpCreate::interface, "CreateDump");
Andrew Geissler55e96ac2022-04-19 11:44:53 -0400218 method.append(
219 std::vector<
220 std::pair<std::string, std::variant<std::string, uint64_t>>>());
221 try
222 {
223 bus.call_noreply(method);
224 }
Patrick Williamsf053e6f2022-07-22 19:26:54 -0500225 catch (const sdbusplus::exception_t& e)
Andrew Geissler55e96ac2022-04-19 11:44:53 -0400226 {
227 error("Failed to create BMC dump, exception:{ERROR}", "ERROR", e);
228 // just continue, this is error path anyway so we're just collecting
229 // what we can
230 }
231}
232
NodeMan9727d1e142022-07-27 15:10:07 -0500233bool checkACLoss(size_t& chassisId)
234{
Patrick Williams1b2c3c02024-08-16 15:20:29 -0400235 std::string chassisLostPowerFileFmt =
236 std::format(CHASSIS_LOST_POWER_FILE, chassisId);
NodeMan9727d1e142022-07-27 15:10:07 -0500237
238 std::filesystem::path chassisPowerLossFile{chassisLostPowerFileFmt};
Pavithra Barithaya44bbf112024-06-21 11:43:30 -0500239 return std::filesystem::exists(chassisPowerLossFile);
NodeMan9727d1e142022-07-27 15:10:07 -0500240}
241
Andrew Geisslerfc1020f2023-05-24 17:07:38 -0400242bool isBmcReady(sdbusplus::bus_t& bus)
243{
Patrick Williams9a286db2024-01-17 06:29:47 -0600244 using BMC = sdbusplus::client::xyz::openbmc_project::state::BMC<>;
245 auto bmcPath = sdbusplus::message::object_path(BMC::namespace_path::value) /
246 BMC::namespace_path::bmc;
247
Patrick Williams1b2c3c02024-08-16 15:20:29 -0400248 auto bmcState =
249 getProperty(bus, bmcPath.str, BMC::interface, "CurrentBMCState");
Patrick Williams9a286db2024-01-17 06:29:47 -0600250
251 if (sdbusplus::message::convert_from_string<BMC::BMCState>(bmcState) !=
252 BMC::BMCState::Ready)
Andrew Geisslerfc1020f2023-05-24 17:07:38 -0400253 {
254 debug("BMC State is {BMC_STATE}", "BMC_STATE", bmcState);
255 return false;
256 }
257 return true;
258}
259
Potin Lai08865452023-11-07 23:28:11 +0800260bool waitBmcReady(sdbusplus::bus_t& bus, std::chrono::seconds timeout)
261{
262 while (timeout.count() != 0)
263 {
264 timeout--;
265 if (isBmcReady(bus))
266 {
267 return true;
268 }
269 std::this_thread::sleep_for(std::chrono::seconds(1));
270 }
271 return false;
272}
273
Thang Tran9f381522024-10-18 10:11:01 +0700274#ifdef CHECK_FWUPDATE_BEFORE_DO_TRANSITION
275bool isFirmwareUpdating(sdbusplus::bus_t& bus)
276{
277 /*
278 * This method looks for ActivationBlocksTransition interface, if any object
279 * path is including this interface, the Transition action should be
280 * prevented.
281 */
282 auto mapper = bus.new_method_call(
283 ObjectMapper::default_service, ObjectMapper::instance_path,
284 ObjectMapper::interface, "GetSubTreePaths");
285
286 mapper.append("/", 0, std::vector<std::string>({ActBlockTrans::interface}));
287
288 std::vector<std::string> mapperResponse;
289
290 try
291 {
292 auto mapperResponseMsg = bus.call(mapper);
293
294 mapperResponseMsg.read(mapperResponse);
295 }
296 catch (const sdbusplus::exception_t& e)
297 {
298 error("Error in mapper call with root path, interface "
299 "ActivationBlocksTransition, and exception {ERROR}",
300 "ERROR", e);
301 return false;
302 }
303
304 return !mapperResponse.empty();
305}
306#endif // CHECK_FWUPDATE_BEFORE_DO_TRANSITION
307
Carol Wangdc059392020-03-13 17:39:17 +0800308} // namespace utils
309} // namespace manager
310} // namespace state
311} // namespace phosphor