1 /* 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> 19 #include <experimental/filesystem> 20 #include <fstream> 21 #include <regex> 22 #include <sdbusplus/asio/connection.hpp> 23 #include <sdbusplus/bus/match.hpp> 24 25 namespace fs = std::experimental::filesystem; 26 const static constexpr char* POWER_INTERFACE_NAME = 27 "xyz.openbmc_project.Chassis.Control.Power"; 28 const static constexpr char* POWER_OBJECT_NAME = 29 "/xyz/openbmc_project/Chassis/Control/Power0"; 30 31 bool getSensorConfiguration( 32 const std::string& type, 33 const std::shared_ptr<sdbusplus::asio::connection>& dbusConnection, 34 ManagedObjectType& resp, bool useCache) 35 { 36 static ManagedObjectType managedObj; 37 38 if (!useCache) 39 { 40 managedObj.clear(); 41 sdbusplus::message::message getManagedObjects = 42 dbusConnection->new_method_call( 43 ENTITY_MANAGER_NAME, "/", "org.freedesktop.DBus.ObjectManager", 44 "GetManagedObjects"); 45 bool err = false; 46 try 47 { 48 sdbusplus::message::message reply = 49 dbusConnection->call(getManagedObjects); 50 err = reply.is_method_error(); 51 if (!err) 52 { 53 reply.read(managedObj); 54 } 55 } 56 catch (const sdbusplus::exception::exception&) 57 { 58 err = true; 59 } 60 61 if (err) 62 { 63 std::cerr << "Error communicating to entity manager\n"; 64 return false; 65 } 66 } 67 for (const auto& pathPair : managedObj) 68 { 69 std::vector<boost::container::flat_map<std::string, BasicVariantType>> 70 sensorData; 71 bool correctType = false; 72 for (const auto& entry : pathPair.second) 73 { 74 if (boost::starts_with(entry.first, type)) 75 { 76 correctType = true; 77 break; 78 } 79 } 80 if (correctType) 81 { 82 resp.emplace(pathPair); 83 } 84 } 85 return true; 86 } 87 88 bool find_files(const fs::path dir_path, const std::string& match_string, 89 std::vector<fs::path>& found_paths, unsigned int symlink_depth) 90 { 91 if (!fs::exists(dir_path)) 92 return false; 93 94 fs::directory_iterator end_itr; 95 std::regex search(match_string); 96 std::smatch match; 97 for (auto& p : fs::recursive_directory_iterator(dir_path)) 98 { 99 std::string path = p.path().string(); 100 if (!is_directory(p)) 101 { 102 if (std::regex_search(path, match, search)) 103 found_paths.emplace_back(p.path()); 104 } 105 // since we're using a recursive iterator, these should only be symlink 106 // dirs 107 else if (symlink_depth) 108 { 109 find_files(p.path(), match_string, found_paths, symlink_depth - 1); 110 } 111 } 112 return true; 113 } 114 115 // initially returns false, then sets up matches and returns status 116 // should be called once first to initialize 117 bool isPowerOn(const std::shared_ptr<sdbusplus::asio::connection>& conn) 118 { 119 static std::unique_ptr<sdbusplus::bus::match::match> powerMatch = nullptr; 120 static bool powerStatusOn = false; 121 122 if (powerMatch != nullptr) 123 { 124 return powerStatusOn; 125 } 126 127 // create a match for powergood changes, first time do a method call to 128 // return the correct value 129 std::function<void(sdbusplus::message::message & message)> eventHandler = 130 [&powerStatusOn](sdbusplus::message::message& message) { 131 std::string objectName; 132 boost::container::flat_map<std::string, 133 sdbusplus::message::variant<int32_t>> 134 values; 135 message.read(objectName, values); 136 auto findPgood = values.find("pgood"); 137 if (findPgood != values.end()) 138 { 139 powerStatusOn = sdbusplus::message::variant_ns::get<int32_t>( 140 findPgood->second); 141 } 142 }; 143 144 powerMatch = std::make_unique<sdbusplus::bus::match::match>( 145 static_cast<sdbusplus::bus::bus&>(*conn), 146 "type='signal',interface='org.freedesktop.DBus.Properties',path_" 147 "namespace='/xyz/openbmc_project/Chassis/Control/" 148 "power0',arg0='xyz.openbmc_project.Chassis.Control.Power'", 149 eventHandler); 150 151 conn->async_method_call( 152 [&powerStatusOn](boost::system::error_code ec, 153 const sdbusplus::message::variant<int32_t>& pgood) { 154 if (ec) 155 { 156 std::cerr << "Error getting initial power status\n"; 157 return; 158 } 159 powerStatusOn = sdbusplus::message::variant_ns::get<int32_t>(pgood); 160 }, 161 POWER_INTERFACE_NAME, POWER_OBJECT_NAME, 162 "org.freedesktop.DBus.Properties", "Get", "pgood"); 163 164 return powerStatusOn; 165 }