blob: 37b5a85b8e1239646476a1e7b04500364754c0b2 [file] [log] [blame]
James Feist6714a252018-09-10 15:26:18 -07001#pragma once
James Feist87d713a2018-12-06 16:06:24 -08002#include "VariantVisitors.hpp"
3
James Feistc71c1192019-09-18 14:31:33 -07004#include <boost/algorithm/string/predicate.hpp>
James Feist6714a252018-09-10 15:26:18 -07005#include <boost/container/flat_map.hpp>
James Feist24f02f22019-04-15 11:05:39 -07006#include <filesystem>
James Feist6714a252018-09-10 15:26:18 -07007#include <iostream>
8#include <regex>
9#include <sdbusplus/asio/connection.hpp>
James Feist82bac4c2019-03-11 11:16:53 -070010#include <sdbusplus/asio/object_server.hpp>
James Feist6714a252018-09-10 15:26:18 -070011#include <sdbusplus/message/types.hpp>
12
James Feist58295ad2019-05-30 15:01:41 -070013constexpr const char* gpioPath = "/sys/class/gpio/";
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -070014const constexpr char* jsonStore = "/var/configuration/flattened.json";
15const constexpr char* inventoryPath = "/xyz/openbmc_project/inventory";
16const constexpr char* entityManagerName = "xyz.openbmc_project.EntityManager";
James Feist58295ad2019-05-30 15:01:41 -070017
18constexpr const char* cpuInventoryPath =
19 "/xyz/openbmc_project/inventory/system/chassis/motherboard";
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -070020const std::regex illegalDbusRegex("[^A-Za-z0-9_]");
James Feist6714a252018-09-10 15:26:18 -070021
22using BasicVariantType =
James Feist3eb82622019-02-08 13:10:22 -080023 std::variant<std::vector<std::string>, std::string, int64_t, uint64_t,
24 double, int32_t, uint32_t, int16_t, uint16_t, uint8_t, bool>;
James Feist6714a252018-09-10 15:26:18 -070025
26using ManagedObjectType = boost::container::flat_map<
27 sdbusplus::message::object_path,
28 boost::container::flat_map<
29 std::string,
30 boost::container::flat_map<std::string, BasicVariantType>>>;
31using SensorData = boost::container::flat_map<
32 std::string, boost::container::flat_map<std::string, BasicVariantType>>;
33
James Feista5e58722019-04-22 14:43:11 -070034using GetSubTreeType = std::vector<
35 std::pair<std::string,
36 std::vector<std::pair<std::string, std::vector<std::string>>>>>;
James Feist87d713a2018-12-06 16:06:24 -080037using SensorBaseConfiguration =
38 std::pair<std::string,
39 boost::container::flat_map<std::string, BasicVariantType>>;
40
James Feistd8bd5622019-06-26 12:09:05 -070041using Association = std::tuple<std::string, std::string, std::string>;
42
James Feistcf3bce62019-01-08 10:07:19 -080043bool findFiles(const std::filesystem::path dirPath,
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -070044 const std::string& matchString,
James Feistcf3bce62019-01-08 10:07:19 -080045 std::vector<std::filesystem::path>& foundPaths,
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -070046 unsigned int symlinkDepth = 1);
James Feist71d31b22019-01-02 16:57:54 -080047bool isPowerOn(void);
James Feistfc94b212019-02-06 16:14:51 -080048bool hasBiosPost(void);
James Feist71d31b22019-01-02 16:57:54 -080049void setupPowerMatch(const std::shared_ptr<sdbusplus::asio::connection>& conn);
James Feist6714a252018-09-10 15:26:18 -070050bool getSensorConfiguration(
51 const std::string& type,
52 const std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
James Feist87d713a2018-12-06 16:06:24 -080053 ManagedObjectType& resp, bool useCache = false);
54
James Feist82bac4c2019-03-11 11:16:53 -070055void createAssociation(
56 std::shared_ptr<sdbusplus::asio::dbus_interface>& association,
57 const std::string& path);
58
James Feist87d713a2018-12-06 16:06:24 -080059// replaces limits if MinReading and MaxReading are found.
60void findLimits(std::pair<double, double>& limits,
James Feist40a72142018-12-21 10:09:53 -080061 const SensorBaseConfiguration* data);
62
James Feistfc94b212019-02-06 16:14:51 -080063enum class PowerState
James Feist6ef20402019-01-07 16:45:08 -080064{
65 on,
James Feistfc94b212019-02-06 16:14:51 -080066 biosPost,
James Feist6ef20402019-01-07 16:45:08 -080067 always
68};
69
James Feista5e58722019-04-22 14:43:11 -070070namespace mapper
71{
72constexpr const char* busName = "xyz.openbmc_project.ObjectMapper";
73constexpr const char* path = "/xyz/openbmc_project/object_mapper";
74constexpr const char* interface = "xyz.openbmc_project.ObjectMapper";
75constexpr const char* subtree = "GetSubTree";
76} // namespace mapper
77
78namespace properties
79{
80constexpr const char* interface = "org.freedesktop.DBus.Properties";
81constexpr const char* get = "Get";
82} // namespace properties
83
James Feist52497fd2019-06-07 13:01:33 -070084namespace power
85{
86const static constexpr char* busname = "xyz.openbmc_project.State.Host";
87const static constexpr char* interface = "xyz.openbmc_project.State.Host";
88const static constexpr char* path = "/xyz/openbmc_project/state/host0";
89const static constexpr char* property = "CurrentHostState";
90} // namespace power
91namespace post
92{
93const static constexpr char* busname =
94 "xyz.openbmc_project.State.OperatingSystem";
95const static constexpr char* interface =
96 "xyz.openbmc_project.State.OperatingSystem.Status";
97const static constexpr char* path = "/xyz/openbmc_project/state/os";
98const static constexpr char* property = "OperatingSystemState";
99} // namespace post
100
James Feist2adc95c2019-09-30 14:55:28 -0700101namespace association
102{
103const static constexpr char* interface =
104 "xyz.openbmc_project.Association.Definitions";
105} // namespace association
106
James Feist40a72142018-12-21 10:09:53 -0800107template <typename T>
108inline T loadVariant(
109 const boost::container::flat_map<std::string, BasicVariantType>& data,
110 const std::string& key)
111{
112 auto it = data.find(key);
113 if (it == data.end())
114 {
115 std::cerr << "Configuration missing " << key << "\n";
116 throw std::invalid_argument("Key Missing");
117 }
118 if constexpr (std::is_same_v<T, double>)
119 {
James Feist3eb82622019-02-08 13:10:22 -0800120 return std::visit(VariantToDoubleVisitor(), it->second);
James Feist40a72142018-12-21 10:09:53 -0800121 }
James Feist6ef20402019-01-07 16:45:08 -0800122 else if constexpr (std::is_unsigned_v<T>)
123 {
James Feist3eb82622019-02-08 13:10:22 -0800124 return std::visit(VariantToUnsignedIntVisitor(), it->second);
James Feist6ef20402019-01-07 16:45:08 -0800125 }
James Feist40a72142018-12-21 10:09:53 -0800126 else if constexpr (std::is_same_v<T, std::string>)
127 {
James Feist3eb82622019-02-08 13:10:22 -0800128 return std::visit(VariantToStringVisitor(), it->second);
James Feist40a72142018-12-21 10:09:53 -0800129 }
130 else
131 {
James Feist52497fd2019-06-07 13:01:33 -0700132 static_assert(!std::is_same_v<T, T>, "Type Not Implemented");
James Feist40a72142018-12-21 10:09:53 -0800133 }
134}
James Feistfc94b212019-02-06 16:14:51 -0800135
136inline void setReadState(const std::string& str, PowerState& val)
137{
138
139 if (str == "On")
140 {
141 val = PowerState::on;
142 }
143 else if (str == "BiosPost")
144 {
145 val = PowerState::biosPost;
146 }
147 else if (str == "Always")
148 {
149 val = PowerState::always;
150 }
151}
Cheng C Yang5580f2f2019-09-19 09:01:47 +0800152
153void createInventoryAssoc(
154 std::shared_ptr<sdbusplus::asio::connection> conn,
155 std::shared_ptr<sdbusplus::asio::dbus_interface> association,
156 const std::string& path);
James Feistc71c1192019-09-18 14:31:33 -0700157
158struct GetSensorConfiguration
159 : std::enable_shared_from_this<GetSensorConfiguration>
160{
161 GetSensorConfiguration(
162 std::shared_ptr<sdbusplus::asio::connection> connection,
163 std::function<void(ManagedObjectType& resp)>&& callbackFunc) :
164 dbusConnection(connection),
165 callback(std::move(callbackFunc))
166 {
167 }
168 void getConfiguration(const std::vector<std::string>& interfaces)
169 {
170 std::shared_ptr<GetSensorConfiguration> self = shared_from_this();
171 dbusConnection->async_method_call(
172 [self, interfaces](const boost::system::error_code ec,
173 const GetSubTreeType& ret) {
174 if (ec)
175 {
176 std::cerr << "Error calling mapper\n";
177 return;
178 }
179 for (const auto& [path, objDict] : ret)
180 {
181 if (objDict.empty())
182 {
183 return;
184 }
185 const std::string& owner = objDict.begin()->first;
186
187 for (const std::string& interface : objDict.begin()->second)
188 {
189 // anything that starts with a requested configuration
190 // is good
191 if (std::find_if(
192 interfaces.begin(), interfaces.end(),
193 [interface](const std::string& possible) {
194 return boost::starts_with(interface,
195 possible);
196 }) == interfaces.end())
197 {
198 continue;
199 }
200
201 self->dbusConnection->async_method_call(
202 [self, path, interface](
203 const boost::system::error_code ec,
204 boost::container::flat_map<
205 std::string, BasicVariantType>& data) {
206 if (ec)
207 {
208 std::cerr << "Error getting " << path
209 << "\n";
210 return;
211 }
212 self->respData[path][interface] =
213 std::move(data);
214 },
215 owner, path, "org.freedesktop.DBus.Properties",
216 "GetAll", interface);
217 }
218 }
219 },
220 mapper::busName, mapper::path, mapper::interface, mapper::subtree,
221 "/", 0, interfaces);
222 }
223
224 ~GetSensorConfiguration()
225 {
226 callback(respData);
227 }
228
229 std::shared_ptr<sdbusplus::asio::connection> dbusConnection;
230 std::function<void(ManagedObjectType& resp)> callback;
231 ManagedObjectType respData;
232};