1 /* 2 // Copyright (c) 2019 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 <boost/algorithm/string/predicate.hpp> 18 #include <boost/asio/io_context.hpp> 19 #include <boost/asio/steady_timer.hpp> 20 #include <boost/container/flat_map.hpp> 21 #include <cstdint> 22 #include <iostream> 23 #include <sdbusplus/asio/connection.hpp> 24 #include <string> 25 #include <variant> 26 #include <vector> 27 28 using GetSubTreeType = std::vector< 29 std::pair<std::string, 30 std::vector<std::pair<std::string, std::vector<std::string>>>>>; 31 using BasicVariantType = 32 std::variant<std::vector<std::string>, std::string, int64_t, uint64_t, 33 double, int32_t, uint32_t, int16_t, uint16_t, uint8_t, bool>; 34 using Association = std::tuple<std::string, std::string, std::string>; 35 36 namespace mapper 37 { 38 constexpr const char* busName = "xyz.openbmc_project.ObjectMapper"; 39 constexpr const char* path = "/xyz/openbmc_project/object_mapper"; 40 constexpr const char* interface = "xyz.openbmc_project.ObjectMapper"; 41 constexpr const char* subtree = "GetSubTree"; 42 } // namespace mapper 43 44 namespace entityManager 45 { 46 constexpr const char* busName = "xyz.openbmc_project.EntityManager"; 47 } // namespace entityManager 48 49 namespace inventory 50 { 51 constexpr const char* interface = "xyz.openbmc_project.Inventory.Item"; 52 } // namespace inventory 53 54 namespace ledGroup 55 { 56 constexpr const char* interface = "xyz.openbmc_project.Led.Group"; 57 constexpr const char* asserted = "Asserted"; 58 } // namespace ledGroup 59 60 namespace properties 61 { 62 constexpr const char* interface = "org.freedesktop.DBus.Properties"; 63 constexpr const char* get = "Get"; 64 } // namespace properties 65 66 namespace power 67 { 68 const static constexpr char* busname = "xyz.openbmc_project.State.Host"; 69 const static constexpr char* interface = "xyz.openbmc_project.State.Host"; 70 const static constexpr char* path = "/xyz/openbmc_project/state/host0"; 71 const static constexpr char* property = "CurrentHostState"; 72 } // namespace power 73 74 namespace association 75 { 76 const static constexpr char* interface = 77 "xyz.openbmc_project.Association.Definitions"; 78 } // namespace association 79 80 namespace hsbp 81 { 82 enum class registers : uint8_t 83 { 84 fpgaIdH = 0x0, 85 fpgaIdL = 0x1, 86 typeId = 0x2, 87 bootVer = 0x3, 88 fpgaVer = 0x4, 89 securityRev = 0x5, 90 funSupported = 0x6, 91 numDisks = 0x7, 92 presence = 0x8, 93 ssdIFDET = 0x9, 94 ifdetPart = 0xA, 95 statusLocate = 0xB, 96 statusFail = 0xC, 97 statusRebuild = 0xD, 98 ledOverride = 0xE, 99 ledStatus = 0xF, 100 ledPattern0 = 0x10, 101 ledPattern1 = 0x11, 102 ledPattern2 = 0x12, 103 ledPattern3 = 0x13, 104 ledPattern4 = 0x14, 105 ledPattern5 = 0x15, 106 ledPattern6 = 0x16, 107 ledPattern7 = 0x17, 108 }; 109 110 } // namespace hsbp 111 112 static std::unique_ptr<sdbusplus::bus::match::match> powerMatch = nullptr; 113 static bool powerStatusOn = false; 114 115 bool isPowerOn(void) 116 { 117 if (!powerMatch) 118 { 119 throw std::runtime_error("Power Match Not Created"); 120 } 121 return powerStatusOn; 122 } 123 124 void setupPowerMatch(const std::shared_ptr<sdbusplus::asio::connection>& conn) 125 { 126 static boost::asio::steady_timer timer(conn->get_io_context()); 127 // create a match for powergood changes, first time do a method call to 128 // cache the correct value 129 if (powerMatch) 130 { 131 return; 132 } 133 134 powerMatch = std::make_unique<sdbusplus::bus::match::match>( 135 static_cast<sdbusplus::bus::bus&>(*conn), 136 "type='signal',interface='" + std::string(properties::interface) + 137 "',path='" + std::string(power::path) + "',arg0='" + 138 std::string(power::interface) + "'", 139 [](sdbusplus::message::message& message) { 140 std::string objectName; 141 boost::container::flat_map<std::string, std::variant<std::string>> 142 values; 143 message.read(objectName, values); 144 auto findState = values.find(power::property); 145 if (findState != values.end()) 146 { 147 bool on = boost::ends_with( 148 std::get<std::string>(findState->second), "Running"); 149 if (!on) 150 { 151 timer.cancel(); 152 powerStatusOn = false; 153 return; 154 } 155 // on comes too quickly 156 timer.expires_after(std::chrono::seconds(10)); 157 timer.async_wait([](boost::system::error_code ec) { 158 if (ec == boost::asio::error::operation_aborted) 159 { 160 return; 161 } 162 else if (ec) 163 { 164 std::cerr << "Timer error " << ec.message() << "\n"; 165 return; 166 } 167 powerStatusOn = true; 168 }); 169 } 170 }); 171 172 conn->async_method_call( 173 [](boost::system::error_code ec, 174 const std::variant<std::string>& state) { 175 if (ec) 176 { 177 // we commonly come up before power control, we'll capture the 178 // property change later 179 return; 180 } 181 powerStatusOn = 182 boost::ends_with(std::get<std::string>(state), "Running"); 183 }, 184 power::busname, power::path, properties::interface, properties::get, 185 power::interface, power::property); 186 } 187