blob: 0518f6a9ec31ad78780194d39d050829ac1d24d0 [file] [log] [blame]
James Feist6714a252018-09-10 15:26:18 -07001/*
2// Copyright (c) 2017 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16
17#include <Utils.hpp>
18#include <boost/algorithm/string/predicate.hpp>
James Feist24f02f22019-04-15 11:05:39 -070019#include <filesystem>
James Feist6714a252018-09-10 15:26:18 -070020#include <fstream>
21#include <regex>
22#include <sdbusplus/asio/connection.hpp>
James Feist82bac4c2019-03-11 11:16:53 -070023#include <sdbusplus/asio/object_server.hpp>
James Feist6714a252018-09-10 15:26:18 -070024#include <sdbusplus/bus/match.hpp>
25
James Feistcf3bce62019-01-08 10:07:19 -080026namespace fs = std::filesystem;
James Feist6714a252018-09-10 15:26:18 -070027
James Feist6ef20402019-01-07 16:45:08 -080028static bool powerStatusOn = false;
James Feistfc94b212019-02-06 16:14:51 -080029static bool biosHasPost = false;
James Feist58295ad2019-05-30 15:01:41 -070030
James Feist6ef20402019-01-07 16:45:08 -080031static std::unique_ptr<sdbusplus::bus::match::match> powerMatch = nullptr;
James Feist52497fd2019-06-07 13:01:33 -070032static std::unique_ptr<sdbusplus::bus::match::match> postMatch = nullptr;
James Feist71d31b22019-01-02 16:57:54 -080033
James Feist6714a252018-09-10 15:26:18 -070034bool getSensorConfiguration(
35 const std::string& type,
36 const std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
37 ManagedObjectType& resp, bool useCache)
38{
39 static ManagedObjectType managedObj;
40
41 if (!useCache)
42 {
43 managedObj.clear();
44 sdbusplus::message::message getManagedObjects =
45 dbusConnection->new_method_call(
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -070046 entityManagerName, "/", "org.freedesktop.DBus.ObjectManager",
James Feist6714a252018-09-10 15:26:18 -070047 "GetManagedObjects");
48 bool err = false;
49 try
50 {
51 sdbusplus::message::message reply =
52 dbusConnection->call(getManagedObjects);
Yoo, Jae Hyun0e022052018-10-15 14:05:37 -070053 reply.read(managedObj);
James Feist6714a252018-09-10 15:26:18 -070054 }
Jason Ling5747fab2019-10-02 16:46:23 -070055 catch (const sdbusplus::exception::exception& e)
James Feist6714a252018-09-10 15:26:18 -070056 {
Jason Ling5747fab2019-10-02 16:46:23 -070057 std::cerr << "While calling GetManagedObjects on service:"
58 << entityManagerName << " exception name:" << e.name()
59 << "and description:" << e.description()
60 << " was thrown\n";
James Feist6714a252018-09-10 15:26:18 -070061 err = true;
62 }
63
64 if (err)
65 {
66 std::cerr << "Error communicating to entity manager\n";
67 return false;
68 }
69 }
70 for (const auto& pathPair : managedObj)
71 {
72 std::vector<boost::container::flat_map<std::string, BasicVariantType>>
73 sensorData;
74 bool correctType = false;
75 for (const auto& entry : pathPair.second)
76 {
77 if (boost::starts_with(entry.first, type))
78 {
79 correctType = true;
80 break;
81 }
82 }
83 if (correctType)
84 {
85 resp.emplace(pathPair);
86 }
87 }
88 return true;
89}
90
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -070091bool findFiles(const fs::path dirPath, const std::string& matchString,
92 std::vector<fs::path>& foundPaths, unsigned int symlinkDepth)
James Feist6714a252018-09-10 15:26:18 -070093{
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -070094 if (!fs::exists(dirPath))
James Feist6714a252018-09-10 15:26:18 -070095 return false;
96
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -070097 std::regex search(matchString);
James Feist6714a252018-09-10 15:26:18 -070098 std::smatch match;
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -070099 for (auto& p : fs::recursive_directory_iterator(dirPath))
James Feist6714a252018-09-10 15:26:18 -0700100 {
101 std::string path = p.path().string();
102 if (!is_directory(p))
103 {
104 if (std::regex_search(path, match, search))
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -0700105 foundPaths.emplace_back(p.path());
James Feist6714a252018-09-10 15:26:18 -0700106 }
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -0700107 else if (is_symlink(p) && symlinkDepth)
James Feist6714a252018-09-10 15:26:18 -0700108 {
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -0700109 findFiles(p.path(), matchString, foundPaths, symlinkDepth - 1);
James Feist6714a252018-09-10 15:26:18 -0700110 }
111 }
112 return true;
113}
114
James Feist71d31b22019-01-02 16:57:54 -0800115bool isPowerOn(void)
James Feist6714a252018-09-10 15:26:18 -0700116{
James Feist71d31b22019-01-02 16:57:54 -0800117 if (!powerMatch)
James Feist6714a252018-09-10 15:26:18 -0700118 {
James Feist71d31b22019-01-02 16:57:54 -0800119 throw std::runtime_error("Power Match Not Created");
James Feist6714a252018-09-10 15:26:18 -0700120 }
James Feist71d31b22019-01-02 16:57:54 -0800121 return powerStatusOn;
122}
123
James Feistfc94b212019-02-06 16:14:51 -0800124bool hasBiosPost(void)
125{
James Feist52497fd2019-06-07 13:01:33 -0700126 if (!postMatch)
James Feistfc94b212019-02-06 16:14:51 -0800127 {
James Feist52497fd2019-06-07 13:01:33 -0700128 throw std::runtime_error("Post Match Not Created");
James Feistfc94b212019-02-06 16:14:51 -0800129 }
130 return biosHasPost;
131}
132
James Feist71d31b22019-01-02 16:57:54 -0800133void setupPowerMatch(const std::shared_ptr<sdbusplus::asio::connection>& conn)
134{
James Feist43d32fe2019-09-04 10:35:20 -0700135 static boost::asio::steady_timer timer(conn->get_io_context());
James Feist6714a252018-09-10 15:26:18 -0700136 // create a match for powergood changes, first time do a method call to
James Feist71d31b22019-01-02 16:57:54 -0800137 // cache the correct value
James Feist52497fd2019-06-07 13:01:33 -0700138 if (powerMatch)
139 {
140 return;
141 }
James Feist6714a252018-09-10 15:26:18 -0700142
143 powerMatch = std::make_unique<sdbusplus::bus::match::match>(
144 static_cast<sdbusplus::bus::bus&>(*conn),
James Feist52497fd2019-06-07 13:01:33 -0700145 "type='signal',interface='" + std::string(properties::interface) +
146 "',path='" + std::string(power::path) + "',arg0='" +
147 std::string(power::interface) + "'",
148 [](sdbusplus::message::message& message) {
149 std::string objectName;
150 boost::container::flat_map<std::string, std::variant<std::string>>
151 values;
152 message.read(objectName, values);
153 auto findState = values.find(power::property);
154 if (findState != values.end())
James Feist6714a252018-09-10 15:26:18 -0700155 {
James Feist43d32fe2019-09-04 10:35:20 -0700156 bool on = boost::ends_with(
James Feist52497fd2019-06-07 13:01:33 -0700157 std::get<std::string>(findState->second), "Running");
James Feist43d32fe2019-09-04 10:35:20 -0700158 if (!on)
159 {
160 timer.cancel();
161 powerStatusOn = false;
162 return;
163 }
164 // on comes too quickly
165 timer.expires_after(std::chrono::seconds(10));
166 timer.async_wait([](boost::system::error_code ec) {
167 if (ec == boost::asio::error::operation_aborted)
168 {
169 return;
170 }
171 else if (ec)
172 {
173 std::cerr << "Timer error " << ec.message() << "\n";
174 return;
175 }
176 powerStatusOn = true;
177 });
James Feist6714a252018-09-10 15:26:18 -0700178 }
James Feist52497fd2019-06-07 13:01:33 -0700179 });
180
181 postMatch = std::make_unique<sdbusplus::bus::match::match>(
182 static_cast<sdbusplus::bus::bus&>(*conn),
183 "type='signal',interface='" + std::string(properties::interface) +
184 "',path='" + std::string(post::path) + "',arg0='" +
185 std::string(post::interface) + "'",
186 [](sdbusplus::message::message& message) {
187 std::string objectName;
188 boost::container::flat_map<std::string, std::variant<std::string>>
189 values;
190 message.read(objectName, values);
191 auto findState = values.find(post::property);
192 if (findState != values.end())
193 {
194 biosHasPost =
195 std::get<std::string>(findState->second) != "Inactive";
196 }
197 });
James Feistfc94b212019-02-06 16:14:51 -0800198
199 conn->async_method_call(
200 [](boost::system::error_code ec,
James Feist52497fd2019-06-07 13:01:33 -0700201 const std::variant<std::string>& state) {
James Feistfc94b212019-02-06 16:14:51 -0800202 if (ec)
203 {
James Feistcee4ef22019-04-04 11:04:08 -0700204 // we commonly come up before power control, we'll capture the
205 // property change later
James Feistfc94b212019-02-06 16:14:51 -0800206 return;
207 }
James Feist52497fd2019-06-07 13:01:33 -0700208 powerStatusOn =
209 boost::ends_with(std::get<std::string>(state), "Running");
James Feistfc94b212019-02-06 16:14:51 -0800210 },
James Feist52497fd2019-06-07 13:01:33 -0700211 power::busname, power::path, properties::interface, properties::get,
212 power::interface, power::property);
213
214 conn->async_method_call(
215 [](boost::system::error_code ec,
216 const std::variant<std::string>& state) {
217 if (ec)
218 {
219 // we commonly come up before power control, we'll capture the
220 // property change later
221 return;
222 }
223 biosHasPost = std::get<std::string>(state) != "Inactive";
224 },
225 post::busname, post::path, properties::interface, properties::get,
226 post::interface, post::property);
James Feist3f0e8762018-11-27 11:30:42 -0800227}
James Feist87d713a2018-12-06 16:06:24 -0800228
229// replaces limits if MinReading and MaxReading are found.
230void findLimits(std::pair<double, double>& limits,
231 const SensorBaseConfiguration* data)
232{
233 if (!data)
234 {
235 return;
236 }
237 auto maxFind = data->second.find("MaxReading");
238 auto minFind = data->second.find("MinReading");
239
240 if (minFind != data->second.end())
241 {
James Feist3eb82622019-02-08 13:10:22 -0800242 limits.first = std::visit(VariantToDoubleVisitor(), minFind->second);
James Feist87d713a2018-12-06 16:06:24 -0800243 }
244 if (maxFind != data->second.end())
245 {
James Feist3eb82622019-02-08 13:10:22 -0800246 limits.second = std::visit(VariantToDoubleVisitor(), maxFind->second);
James Feist87d713a2018-12-06 16:06:24 -0800247 }
James Feistfc94b212019-02-06 16:14:51 -0800248}
James Feist82bac4c2019-03-11 11:16:53 -0700249
250void createAssociation(
251 std::shared_ptr<sdbusplus::asio::dbus_interface>& association,
252 const std::string& path)
253{
254 if (association)
255 {
James Feistd2543f82019-04-09 11:10:06 -0700256 std::filesystem::path p(path);
257
James Feist82bac4c2019-03-11 11:16:53 -0700258 std::vector<Association> associations;
James Feistd2543f82019-04-09 11:10:06 -0700259 associations.push_back(
James Feistd8bd5622019-06-26 12:09:05 -0700260 Association("chassis", "all_sensors", p.parent_path().string()));
James Feist2adc95c2019-09-30 14:55:28 -0700261 association->register_property("Associations", associations);
James Feist82bac4c2019-03-11 11:16:53 -0700262 association->initialize();
263 }
James Feist43d32fe2019-09-04 10:35:20 -0700264}
Cheng C Yang5580f2f2019-09-19 09:01:47 +0800265
266void setInventoryAssociation(
267 std::shared_ptr<sdbusplus::asio::dbus_interface> association,
268 const std::string& path, const std::string& chassisPath)
269{
270 if (association)
271 {
272 std::filesystem::path p(path);
273
274 std::vector<Association> associations;
275 associations.push_back(
276 Association("inventory", "sensors", p.parent_path().string()));
277 associations.push_back(
278 Association("chassis", "all_sensors", chassisPath));
James Feist2adc95c2019-09-30 14:55:28 -0700279 association->register_property("Associations", associations);
Cheng C Yang5580f2f2019-09-19 09:01:47 +0800280 association->initialize();
281 }
282}
283
284void createInventoryAssoc(
285 std::shared_ptr<sdbusplus::asio::connection> conn,
286 std::shared_ptr<sdbusplus::asio::dbus_interface> association,
287 const std::string& path)
288{
289 if (!association)
290 {
291 return;
292 }
293 conn->async_method_call(
294 [association, path](const boost::system::error_code ec,
295 const std::vector<std::string>& ret) {
296 if (ec)
297 {
298 std::cerr << "Error calling mapper\n";
299 return;
300 }
301 for (const auto& object : ret)
302 {
303 setInventoryAssociation(association, path, object);
304 }
305 },
306 mapper::busName, mapper::path, mapper::interface, "GetSubTreePaths",
307 "/xyz/openbmc_project/inventory/system", 2,
308 std::array<std::string, 1>{
309 "xyz.openbmc_project.Inventory.Item.System"});
310}