blob: 26a1e8b27313692ee087067e883a0b7c8dab973f [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>
11#include <xyz/openbmc_project/State/BMC/client.hpp>
Carol Wangdc059392020-03-13 17:39:17 +080012
Andrew Geissler48a4e5e2023-02-15 18:23:34 -060013#include <chrono>
NodeMan9727d1e142022-07-27 15:10:07 -050014#include <filesystem>
Patrick Williams78c066f2024-02-13 12:25:58 -060015#include <format>
NodeMan9727d1e142022-07-27 15:10:07 -050016
Carol Wangdc059392020-03-13 17:39:17 +080017namespace phosphor
18{
19namespace state
20{
21namespace manager
22{
23namespace utils
24{
25
Andrew Geissler48a4e5e2023-02-15 18:23:34 -060026using namespace std::literals::chrono_literals;
27
Andrew Geissler8ffdb262021-09-20 15:25:19 -050028PHOSPHOR_LOG2_USING;
Carol Wangdc059392020-03-13 17:39:17 +080029
Andrew Geissler928bbf12023-02-14 13:30:14 -060030constexpr auto SYSTEMD_SERVICE = "org.freedesktop.systemd1";
31constexpr auto SYSTEMD_OBJ_PATH = "/org/freedesktop/systemd1";
32constexpr auto SYSTEMD_INTERFACE = "org.freedesktop.systemd1.Manager";
Carol Wangdc059392020-03-13 17:39:17 +080033constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
34
Patrick Williams9a286db2024-01-17 06:29:47 -060035using ObjectMapper = sdbusplus::client::xyz::openbmc_project::ObjectMapper<>;
36
Patrick Williams5c4a0822023-02-28 02:40:35 -060037void subscribeToSystemdSignals(sdbusplus::bus_t& bus)
Andrew Geissler928bbf12023-02-14 13:30:14 -060038{
39 auto method = bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_OBJ_PATH,
40 SYSTEMD_INTERFACE, "Subscribe");
41
42 try
43 {
Andrew Geissler48a4e5e2023-02-15 18:23:34 -060044 // On OpenBMC based systems, systemd has had a few situations where it
45 // has been unable to respond to this call within the default d-bus
46 // timeout of 25 seconds. This is due to the large amount of work being
47 // done by systemd during OpenBMC startup. Set the timeout for this call
48 // to 60 seconds (worst case seen was around 30s so double it).
49 bus.call(method, 60s);
Andrew Geissler928bbf12023-02-14 13:30:14 -060050 }
51 catch (const sdbusplus::exception_t& e)
52 {
53 error("Failed to subscribe to systemd signals: {ERROR}", "ERROR", e);
54 throw std::runtime_error("Unable to subscribe to systemd signals");
55 }
56 return;
57}
58
Patrick Williams5c4a0822023-02-28 02:40:35 -060059std::string getService(sdbusplus::bus_t& bus, std::string path,
Carol Wangdc059392020-03-13 17:39:17 +080060 std::string interface)
61{
Patrick Williams9a286db2024-01-17 06:29:47 -060062 auto mapper = bus.new_method_call(ObjectMapper::default_service,
63 ObjectMapper::instance_path,
64 ObjectMapper::interface, "GetObject");
Carol Wangdc059392020-03-13 17:39:17 +080065
66 mapper.append(path, std::vector<std::string>({interface}));
67
68 std::vector<std::pair<std::string, std::vector<std::string>>>
69 mapperResponse;
70
71 try
72 {
73 auto mapperResponseMsg = bus.call(mapper);
74
75 mapperResponseMsg.read(mapperResponse);
76 if (mapperResponse.empty())
77 {
Andrew Geisslerad65b2d2021-09-21 12:53:29 -050078 error(
79 "Error no matching service with path {PATH} and interface {INTERFACE}",
80 "PATH", path, "INTERFACE", interface);
Carol Wangdc059392020-03-13 17:39:17 +080081 throw std::runtime_error("Error no matching service");
82 }
83 }
Patrick Williamsf053e6f2022-07-22 19:26:54 -050084 catch (const sdbusplus::exception_t& e)
Carol Wangdc059392020-03-13 17:39:17 +080085 {
Andrew Geissler8ffdb262021-09-20 15:25:19 -050086 error("Error in mapper call with path {PATH}, interface "
87 "{INTERFACE}, and exception {ERROR}",
88 "PATH", path, "INTERFACE", interface, "ERROR", e);
Carol Wangdc059392020-03-13 17:39:17 +080089 throw;
90 }
91
92 return mapperResponse.begin()->first;
93}
94
Patrick Williamsf053e6f2022-07-22 19:26:54 -050095std::string getProperty(sdbusplus::bus_t& bus, const std::string& path,
Andrew Geissler49e67132022-01-26 14:27:52 -060096 const std::string& interface,
97 const std::string& propertyName)
98{
99 std::variant<std::string> property;
100 std::string service = getService(bus, path, interface);
101
102 auto method = bus.new_method_call(service.c_str(), path.c_str(),
103 PROPERTY_INTERFACE, "Get");
104
105 method.append(interface, propertyName);
106
107 try
108 {
109 auto reply = bus.call(method);
110 reply.read(property);
111 }
Patrick Williamsf053e6f2022-07-22 19:26:54 -0500112 catch (const sdbusplus::exception_t& e)
Andrew Geissler49e67132022-01-26 14:27:52 -0600113 {
114 error("Error in property Get, error {ERROR}, property {PROPERTY}",
115 "ERROR", e, "PROPERTY", propertyName);
116 throw;
117 }
118
119 if (std::get<std::string>(property).empty())
120 {
121 error("Error reading property response for {PROPERTY}", "PROPERTY",
122 propertyName);
123 throw std::runtime_error("Error reading property response");
124 }
125
126 return std::get<std::string>(property);
127}
128
Patrick Williamsf053e6f2022-07-22 19:26:54 -0500129void setProperty(sdbusplus::bus_t& bus, const std::string& path,
Carol Wangdc059392020-03-13 17:39:17 +0800130 const std::string& interface, const std::string& property,
131 const std::string& value)
132{
Patrick Williams2975e262020-05-13 18:01:09 -0500133 std::variant<std::string> variantValue = value;
Carol Wangdc059392020-03-13 17:39:17 +0800134 std::string service = getService(bus, path, interface);
135
136 auto method = bus.new_method_call(service.c_str(), path.c_str(),
137 PROPERTY_INTERFACE, "Set");
138
139 method.append(interface, property, variantValue);
140 bus.call_noreply(method);
141
142 return;
143}
144
Andrew Geisslerf8ae6a02022-01-21 17:00:20 -0600145int getGpioValue(const std::string& gpioName)
146{
Andrew Geisslerf8ae6a02022-01-21 17:00:20 -0600147 int gpioval = -1;
148 gpiod_line* line = gpiod_line_find(gpioName.c_str());
149
150 if (nullptr != line)
151 {
152 // take ownership of gpio
153 if (0 != gpiod_line_request_input(line, "state-manager"))
154 {
155 error("Failed request for {GPIO_NAME} GPIO", "GPIO_NAME", gpioName);
156 }
157 else
158 {
159 // get gpio value
160 gpioval = gpiod_line_get_value(line);
161
162 // release ownership of gpio
163 gpiod_line_close_chip(line);
164 }
165 }
166 return gpioval;
167}
168
Andrew Geissler9d4d0c92022-01-26 13:18:12 -0600169void createError(
Patrick Williamsf053e6f2022-07-22 19:26:54 -0500170 sdbusplus::bus_t& bus, const std::string& errorMsg,
Patrick Williams7e969cb2023-08-23 16:24:23 -0500171 sdbusplus::server::xyz::openbmc_project::logging::Entry::Level errLevel,
Andrew Geisslerd49f51e2022-03-07 14:57:07 -0600172 std::map<std::string, std::string> additionalData)
Andrew Geissler9d4d0c92022-01-26 13:18:12 -0600173{
Andrew Geissler9d4d0c92022-01-26 13:18:12 -0600174 try
175 {
Andrew Geisslerd49f51e2022-03-07 14:57:07 -0600176 // Always add the _PID on for some extra logging debug
Andrew Geissler9d4d0c92022-01-26 13:18:12 -0600177 additionalData.emplace("_PID", std::to_string(getpid()));
178
Patrick Williams9a286db2024-01-17 06:29:47 -0600179 using LoggingCreate =
180 sdbusplus::client::xyz::openbmc_project::logging::Create<>;
181
182 auto method = bus.new_method_call(LoggingCreate::default_service,
183 LoggingCreate::instance_path,
184 LoggingCreate::interface, "Create");
Andrew Geissler9d4d0c92022-01-26 13:18:12 -0600185
186 method.append(errorMsg, errLevel, additionalData);
187 auto resp = bus.call(method);
188 }
Patrick Williamsf053e6f2022-07-22 19:26:54 -0500189 catch (const sdbusplus::exception_t& e)
Andrew Geissler9d4d0c92022-01-26 13:18:12 -0600190 {
191 error("sdbusplus D-Bus call exception, error {ERROR} trying to create "
192 "an error with {ERROR_MSG}",
193 "ERROR", e, "ERROR_MSG", errorMsg);
194
195 throw std::runtime_error(
196 "Error in invoking D-Bus logging create interface");
197 }
198 catch (const std::exception& e)
199 {
200 error("D-bus call exception: {ERROR}", "ERROR", e);
201 throw e;
202 }
203}
204
Patrick Williamsf053e6f2022-07-22 19:26:54 -0500205void createBmcDump(sdbusplus::bus_t& bus)
Andrew Geissler55e96ac2022-04-19 11:44:53 -0400206{
Patrick Williams9a286db2024-01-17 06:29:47 -0600207 using DumpCreate = sdbusplus::client::xyz::openbmc_project::dump::Create<>;
208 auto dumpPath =
209 sdbusplus::message::object_path(DumpCreate::namespace_path::value) /
210 DumpCreate::namespace_path::bmc;
211
Patrick Williams1b2c3c02024-08-16 15:20:29 -0400212 auto method =
213 bus.new_method_call(DumpCreate::default_service, dumpPath.str.c_str(),
214 DumpCreate::interface, "CreateDump");
Andrew Geissler55e96ac2022-04-19 11:44:53 -0400215 method.append(
216 std::vector<
217 std::pair<std::string, std::variant<std::string, uint64_t>>>());
218 try
219 {
220 bus.call_noreply(method);
221 }
Patrick Williamsf053e6f2022-07-22 19:26:54 -0500222 catch (const sdbusplus::exception_t& e)
Andrew Geissler55e96ac2022-04-19 11:44:53 -0400223 {
224 error("Failed to create BMC dump, exception:{ERROR}", "ERROR", e);
225 // just continue, this is error path anyway so we're just collecting
226 // what we can
227 }
228}
229
NodeMan9727d1e142022-07-27 15:10:07 -0500230bool checkACLoss(size_t& chassisId)
231{
Patrick Williams1b2c3c02024-08-16 15:20:29 -0400232 std::string chassisLostPowerFileFmt =
233 std::format(CHASSIS_LOST_POWER_FILE, chassisId);
NodeMan9727d1e142022-07-27 15:10:07 -0500234
235 std::filesystem::path chassisPowerLossFile{chassisLostPowerFileFmt};
Pavithra Barithaya44bbf112024-06-21 11:43:30 -0500236 return std::filesystem::exists(chassisPowerLossFile);
NodeMan9727d1e142022-07-27 15:10:07 -0500237}
238
Andrew Geisslerfc1020f2023-05-24 17:07:38 -0400239bool isBmcReady(sdbusplus::bus_t& bus)
240{
Patrick Williams9a286db2024-01-17 06:29:47 -0600241 using BMC = sdbusplus::client::xyz::openbmc_project::state::BMC<>;
242 auto bmcPath = sdbusplus::message::object_path(BMC::namespace_path::value) /
243 BMC::namespace_path::bmc;
244
Patrick Williams1b2c3c02024-08-16 15:20:29 -0400245 auto bmcState =
246 getProperty(bus, bmcPath.str, BMC::interface, "CurrentBMCState");
Patrick Williams9a286db2024-01-17 06:29:47 -0600247
248 if (sdbusplus::message::convert_from_string<BMC::BMCState>(bmcState) !=
249 BMC::BMCState::Ready)
Andrew Geisslerfc1020f2023-05-24 17:07:38 -0400250 {
251 debug("BMC State is {BMC_STATE}", "BMC_STATE", bmcState);
252 return false;
253 }
254 return true;
255}
256
Potin Lai08865452023-11-07 23:28:11 +0800257bool waitBmcReady(sdbusplus::bus_t& bus, std::chrono::seconds timeout)
258{
259 while (timeout.count() != 0)
260 {
261 timeout--;
262 if (isBmcReady(bus))
263 {
264 return true;
265 }
266 std::this_thread::sleep_for(std::chrono::seconds(1));
267 }
268 return false;
269}
270
Carol Wangdc059392020-03-13 17:39:17 +0800271} // namespace utils
272} // namespace manager
273} // namespace state
274} // namespace phosphor