blob: d90813d4726ce5b74c7edd96e9a3def58447c351 [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;
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -070027const static constexpr char* powerInterfaceName =
James Feist6714a252018-09-10 15:26:18 -070028 "xyz.openbmc_project.Chassis.Control.Power";
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -070029const static constexpr char* powerObjectName =
James Feist6714a252018-09-10 15:26:18 -070030 "/xyz/openbmc_project/Chassis/Control/Power0";
31
James Feist6ef20402019-01-07 16:45:08 -080032static bool powerStatusOn = false;
James Feistfc94b212019-02-06 16:14:51 -080033static bool biosHasPost = false;
James Feist58295ad2019-05-30 15:01:41 -070034
James Feist6ef20402019-01-07 16:45:08 -080035static std::unique_ptr<sdbusplus::bus::match::match> powerMatch = nullptr;
James Feist71d31b22019-01-02 16:57:54 -080036
James Feist6714a252018-09-10 15:26:18 -070037bool getSensorConfiguration(
38 const std::string& type,
39 const std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
40 ManagedObjectType& resp, bool useCache)
41{
42 static ManagedObjectType managedObj;
43
44 if (!useCache)
45 {
46 managedObj.clear();
47 sdbusplus::message::message getManagedObjects =
48 dbusConnection->new_method_call(
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -070049 entityManagerName, "/", "org.freedesktop.DBus.ObjectManager",
James Feist6714a252018-09-10 15:26:18 -070050 "GetManagedObjects");
51 bool err = false;
52 try
53 {
54 sdbusplus::message::message reply =
55 dbusConnection->call(getManagedObjects);
Yoo, Jae Hyun0e022052018-10-15 14:05:37 -070056 reply.read(managedObj);
James Feist6714a252018-09-10 15:26:18 -070057 }
58 catch (const sdbusplus::exception::exception&)
59 {
60 err = true;
61 }
62
63 if (err)
64 {
65 std::cerr << "Error communicating to entity manager\n";
66 return false;
67 }
68 }
69 for (const auto& pathPair : managedObj)
70 {
71 std::vector<boost::container::flat_map<std::string, BasicVariantType>>
72 sensorData;
73 bool correctType = false;
74 for (const auto& entry : pathPair.second)
75 {
76 if (boost::starts_with(entry.first, type))
77 {
78 correctType = true;
79 break;
80 }
81 }
82 if (correctType)
83 {
84 resp.emplace(pathPair);
85 }
86 }
87 return true;
88}
89
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -070090bool findFiles(const fs::path dirPath, const std::string& matchString,
91 std::vector<fs::path>& foundPaths, unsigned int symlinkDepth)
James Feist6714a252018-09-10 15:26:18 -070092{
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -070093 if (!fs::exists(dirPath))
James Feist6714a252018-09-10 15:26:18 -070094 return false;
95
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -070096 std::regex search(matchString);
James Feist6714a252018-09-10 15:26:18 -070097 std::smatch match;
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -070098 for (auto& p : fs::recursive_directory_iterator(dirPath))
James Feist6714a252018-09-10 15:26:18 -070099 {
100 std::string path = p.path().string();
101 if (!is_directory(p))
102 {
103 if (std::regex_search(path, match, search))
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -0700104 foundPaths.emplace_back(p.path());
James Feist6714a252018-09-10 15:26:18 -0700105 }
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -0700106 else if (is_symlink(p) && symlinkDepth)
James Feist6714a252018-09-10 15:26:18 -0700107 {
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -0700108 findFiles(p.path(), matchString, foundPaths, symlinkDepth - 1);
James Feist6714a252018-09-10 15:26:18 -0700109 }
110 }
111 return true;
112}
113
James Feist71d31b22019-01-02 16:57:54 -0800114bool isPowerOn(void)
James Feist6714a252018-09-10 15:26:18 -0700115{
James Feist71d31b22019-01-02 16:57:54 -0800116 if (!powerMatch)
James Feist6714a252018-09-10 15:26:18 -0700117 {
James Feist71d31b22019-01-02 16:57:54 -0800118 throw std::runtime_error("Power Match Not Created");
James Feist6714a252018-09-10 15:26:18 -0700119 }
James Feist71d31b22019-01-02 16:57:54 -0800120 return powerStatusOn;
121}
122
James Feistfc94b212019-02-06 16:14:51 -0800123bool hasBiosPost(void)
124{
125 if (!powerMatch)
126 {
127 throw std::runtime_error("Power Match Not Created");
128 }
129 return biosHasPost;
130}
131
James Feist71d31b22019-01-02 16:57:54 -0800132void setupPowerMatch(const std::shared_ptr<sdbusplus::asio::connection>& conn)
133{
James Feist6714a252018-09-10 15:26:18 -0700134 // create a match for powergood changes, first time do a method call to
James Feist71d31b22019-01-02 16:57:54 -0800135 // cache the correct value
James Feist6714a252018-09-10 15:26:18 -0700136 std::function<void(sdbusplus::message::message & message)> eventHandler =
James Feist3f0e8762018-11-27 11:30:42 -0800137 [](sdbusplus::message::message& message) {
James Feist6714a252018-09-10 15:26:18 -0700138 std::string objectName;
James Feist3eb82622019-02-08 13:10:22 -0800139 boost::container::flat_map<std::string, std::variant<int32_t, bool>>
James Feist6714a252018-09-10 15:26:18 -0700140 values;
141 message.read(objectName, values);
142 auto findPgood = values.find("pgood");
143 if (findPgood != values.end())
144 {
James Feist3eb82622019-02-08 13:10:22 -0800145 powerStatusOn = std::get<int32_t>(findPgood->second);
James Feist6714a252018-09-10 15:26:18 -0700146 }
James Feistfc94b212019-02-06 16:14:51 -0800147 auto findPostComplete = values.find("post_complete");
148 if (findPostComplete != values.end())
149 {
James Feist3eb82622019-02-08 13:10:22 -0800150 biosHasPost = std::get<bool>(findPostComplete->second);
James Feistfc94b212019-02-06 16:14:51 -0800151 }
James Feist6714a252018-09-10 15:26:18 -0700152 };
153
154 powerMatch = std::make_unique<sdbusplus::bus::match::match>(
155 static_cast<sdbusplus::bus::bus&>(*conn),
156 "type='signal',interface='org.freedesktop.DBus.Properties',path_"
157 "namespace='/xyz/openbmc_project/Chassis/Control/"
James Feiste86810b2019-02-05 13:13:06 -0800158 "Power0',arg0='xyz.openbmc_project.Chassis.Control.Power'",
James Feist6714a252018-09-10 15:26:18 -0700159 eventHandler);
160
161 conn->async_method_call(
James Feist3eb82622019-02-08 13:10:22 -0800162 [](boost::system::error_code ec, const std::variant<int32_t>& pgood) {
James Feist6714a252018-09-10 15:26:18 -0700163 if (ec)
164 {
James Feistc9445d82019-04-04 08:40:21 -0700165 // we commonly come up before power control, we'll capture the
166 // property change later
James Feist6714a252018-09-10 15:26:18 -0700167 return;
168 }
James Feist3eb82622019-02-08 13:10:22 -0800169 powerStatusOn = std::get<int32_t>(pgood);
James Feist6714a252018-09-10 15:26:18 -0700170 },
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -0700171 powerInterfaceName, powerObjectName, "org.freedesktop.DBus.Properties",
James Feistdc6c55f2018-10-31 12:53:20 -0700172 "Get", powerInterfaceName, "pgood");
James Feistfc94b212019-02-06 16:14:51 -0800173
174 conn->async_method_call(
175 [](boost::system::error_code ec,
James Feist3eb82622019-02-08 13:10:22 -0800176 const std::variant<int32_t>& postComplete) {
James Feistfc94b212019-02-06 16:14:51 -0800177 if (ec)
178 {
James Feistcee4ef22019-04-04 11:04:08 -0700179 // we commonly come up before power control, we'll capture the
180 // property change later
James Feistfc94b212019-02-06 16:14:51 -0800181 return;
182 }
James Feist3eb82622019-02-08 13:10:22 -0800183 biosHasPost = std::get<int32_t>(postComplete);
James Feistfc94b212019-02-06 16:14:51 -0800184 },
185 powerInterfaceName, powerObjectName, "org.freedesktop.DBus.Properties",
186 "Get", powerInterfaceName, "post_complete");
James Feist3f0e8762018-11-27 11:30:42 -0800187}
James Feist87d713a2018-12-06 16:06:24 -0800188
189// replaces limits if MinReading and MaxReading are found.
190void findLimits(std::pair<double, double>& limits,
191 const SensorBaseConfiguration* data)
192{
193 if (!data)
194 {
195 return;
196 }
197 auto maxFind = data->second.find("MaxReading");
198 auto minFind = data->second.find("MinReading");
199
200 if (minFind != data->second.end())
201 {
James Feist3eb82622019-02-08 13:10:22 -0800202 limits.first = std::visit(VariantToDoubleVisitor(), minFind->second);
James Feist87d713a2018-12-06 16:06:24 -0800203 }
204 if (maxFind != data->second.end())
205 {
James Feist3eb82622019-02-08 13:10:22 -0800206 limits.second = std::visit(VariantToDoubleVisitor(), maxFind->second);
James Feist87d713a2018-12-06 16:06:24 -0800207 }
James Feistfc94b212019-02-06 16:14:51 -0800208}
James Feist82bac4c2019-03-11 11:16:53 -0700209
210void createAssociation(
211 std::shared_ptr<sdbusplus::asio::dbus_interface>& association,
212 const std::string& path)
213{
214 if (association)
215 {
James Feistd2543f82019-04-09 11:10:06 -0700216 std::filesystem::path p(path);
217
James Feist82bac4c2019-03-11 11:16:53 -0700218 using Association = std::tuple<std::string, std::string, std::string>;
219 std::vector<Association> associations;
James Feistd2543f82019-04-09 11:10:06 -0700220 associations.push_back(
221 Association("inventory", "sensors", p.parent_path().string()));
James Feist82bac4c2019-03-11 11:16:53 -0700222 association->register_property("associations", associations);
223 association->initialize();
224 }
225}