blob: 9ef652fd1209a2eb5b16a662517c39c8438e7dbe [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
NodeMan9727d1e142022-07-27 15:10:07 -050011#include <filesystem>
12
Carol Wangdc059392020-03-13 17:39:17 +080013namespace phosphor
14{
15namespace state
16{
17namespace manager
18{
19namespace utils
20{
21
Andrew Geissler8ffdb262021-09-20 15:25:19 -050022PHOSPHOR_LOG2_USING;
Carol Wangdc059392020-03-13 17:39:17 +080023
24constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper";
25constexpr auto MAPPER_PATH = "/xyz/openbmc_project/object_mapper";
26constexpr auto MAPPER_INTERFACE = "xyz.openbmc_project.ObjectMapper";
27constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
28
Patrick Williamsf053e6f2022-07-22 19:26:54 -050029std::string getService(sdbusplus::bus_t& bus, std::string path,
Carol Wangdc059392020-03-13 17:39:17 +080030 std::string interface)
31{
32 auto mapper = bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH,
33 MAPPER_INTERFACE, "GetObject");
34
35 mapper.append(path, std::vector<std::string>({interface}));
36
37 std::vector<std::pair<std::string, std::vector<std::string>>>
38 mapperResponse;
39
40 try
41 {
42 auto mapperResponseMsg = bus.call(mapper);
43
44 mapperResponseMsg.read(mapperResponse);
45 if (mapperResponse.empty())
46 {
Andrew Geisslerad65b2d2021-09-21 12:53:29 -050047 error(
48 "Error no matching service with path {PATH} and interface {INTERFACE}",
49 "PATH", path, "INTERFACE", interface);
Carol Wangdc059392020-03-13 17:39:17 +080050 throw std::runtime_error("Error no matching service");
51 }
52 }
Patrick Williamsf053e6f2022-07-22 19:26:54 -050053 catch (const sdbusplus::exception_t& e)
Carol Wangdc059392020-03-13 17:39:17 +080054 {
Andrew Geissler8ffdb262021-09-20 15:25:19 -050055 error("Error in mapper call with path {PATH}, interface "
56 "{INTERFACE}, and exception {ERROR}",
57 "PATH", path, "INTERFACE", interface, "ERROR", e);
Carol Wangdc059392020-03-13 17:39:17 +080058 throw;
59 }
60
61 return mapperResponse.begin()->first;
62}
63
Patrick Williamsf053e6f2022-07-22 19:26:54 -050064std::string getProperty(sdbusplus::bus_t& bus, const std::string& path,
Andrew Geissler49e67132022-01-26 14:27:52 -060065 const std::string& interface,
66 const std::string& propertyName)
67{
68 std::variant<std::string> property;
69 std::string service = getService(bus, path, interface);
70
71 auto method = bus.new_method_call(service.c_str(), path.c_str(),
72 PROPERTY_INTERFACE, "Get");
73
74 method.append(interface, propertyName);
75
76 try
77 {
78 auto reply = bus.call(method);
79 reply.read(property);
80 }
Patrick Williamsf053e6f2022-07-22 19:26:54 -050081 catch (const sdbusplus::exception_t& e)
Andrew Geissler49e67132022-01-26 14:27:52 -060082 {
83 error("Error in property Get, error {ERROR}, property {PROPERTY}",
84 "ERROR", e, "PROPERTY", propertyName);
85 throw;
86 }
87
88 if (std::get<std::string>(property).empty())
89 {
90 error("Error reading property response for {PROPERTY}", "PROPERTY",
91 propertyName);
92 throw std::runtime_error("Error reading property response");
93 }
94
95 return std::get<std::string>(property);
96}
97
Patrick Williamsf053e6f2022-07-22 19:26:54 -050098void setProperty(sdbusplus::bus_t& bus, const std::string& path,
Carol Wangdc059392020-03-13 17:39:17 +080099 const std::string& interface, const std::string& property,
100 const std::string& value)
101{
Patrick Williams2975e262020-05-13 18:01:09 -0500102 std::variant<std::string> variantValue = value;
Carol Wangdc059392020-03-13 17:39:17 +0800103 std::string service = getService(bus, path, interface);
104
105 auto method = bus.new_method_call(service.c_str(), path.c_str(),
106 PROPERTY_INTERFACE, "Set");
107
108 method.append(interface, property, variantValue);
109 bus.call_noreply(method);
110
111 return;
112}
113
Andrew Geisslerf8ae6a02022-01-21 17:00:20 -0600114int getGpioValue(const std::string& gpioName)
115{
Andrew Geisslerf8ae6a02022-01-21 17:00:20 -0600116 int gpioval = -1;
117 gpiod_line* line = gpiod_line_find(gpioName.c_str());
118
119 if (nullptr != line)
120 {
121 // take ownership of gpio
122 if (0 != gpiod_line_request_input(line, "state-manager"))
123 {
124 error("Failed request for {GPIO_NAME} GPIO", "GPIO_NAME", gpioName);
125 }
126 else
127 {
128 // get gpio value
129 gpioval = gpiod_line_get_value(line);
130
131 // release ownership of gpio
132 gpiod_line_close_chip(line);
133 }
134 }
135 return gpioval;
136}
137
Andrew Geissler9d4d0c92022-01-26 13:18:12 -0600138void createError(
Patrick Williamsf053e6f2022-07-22 19:26:54 -0500139 sdbusplus::bus_t& bus, const std::string& errorMsg,
Andrew Geisslerd49f51e2022-03-07 14:57:07 -0600140 sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level errLevel,
141 std::map<std::string, std::string> additionalData)
Andrew Geissler9d4d0c92022-01-26 13:18:12 -0600142{
Andrew Geissler9d4d0c92022-01-26 13:18:12 -0600143 try
144 {
Andrew Geisslerd49f51e2022-03-07 14:57:07 -0600145 // Always add the _PID on for some extra logging debug
Andrew Geissler9d4d0c92022-01-26 13:18:12 -0600146 additionalData.emplace("_PID", std::to_string(getpid()));
147
148 auto method = bus.new_method_call(
149 "xyz.openbmc_project.Logging", "/xyz/openbmc_project/logging",
150 "xyz.openbmc_project.Logging.Create", "Create");
151
152 method.append(errorMsg, errLevel, additionalData);
153 auto resp = bus.call(method);
154 }
Patrick Williamsf053e6f2022-07-22 19:26:54 -0500155 catch (const sdbusplus::exception_t& e)
Andrew Geissler9d4d0c92022-01-26 13:18:12 -0600156 {
157 error("sdbusplus D-Bus call exception, error {ERROR} trying to create "
158 "an error with {ERROR_MSG}",
159 "ERROR", e, "ERROR_MSG", errorMsg);
160
161 throw std::runtime_error(
162 "Error in invoking D-Bus logging create interface");
163 }
164 catch (const std::exception& e)
165 {
166 error("D-bus call exception: {ERROR}", "ERROR", e);
167 throw e;
168 }
169}
170
Patrick Williamsf053e6f2022-07-22 19:26:54 -0500171void createBmcDump(sdbusplus::bus_t& bus)
Andrew Geissler55e96ac2022-04-19 11:44:53 -0400172{
173 auto method = bus.new_method_call(
174 "xyz.openbmc_project.Dump.Manager", "/xyz/openbmc_project/dump/bmc",
175 "xyz.openbmc_project.Dump.Create", "CreateDump");
176 method.append(
177 std::vector<
178 std::pair<std::string, std::variant<std::string, uint64_t>>>());
179 try
180 {
181 bus.call_noreply(method);
182 }
Patrick Williamsf053e6f2022-07-22 19:26:54 -0500183 catch (const sdbusplus::exception_t& e)
Andrew Geissler55e96ac2022-04-19 11:44:53 -0400184 {
185 error("Failed to create BMC dump, exception:{ERROR}", "ERROR", e);
186 // just continue, this is error path anyway so we're just collecting
187 // what we can
188 }
189}
190
NodeMan9727d1e142022-07-27 15:10:07 -0500191bool checkACLoss(size_t& chassisId)
192{
193 std::string chassisLostPowerFileFmt =
194 fmt::sprintf(CHASSIS_LOST_POWER_FILE, chassisId);
195
196 std::filesystem::path chassisPowerLossFile{chassisLostPowerFileFmt};
197 if (std::filesystem::exists(chassisPowerLossFile))
198 {
199 return true;
200 }
201
202 return false;
203}
204
Carol Wangdc059392020-03-13 17:39:17 +0800205} // namespace utils
206} // namespace manager
207} // namespace state
208} // namespace phosphor