blob: 44e7e2e52c843623a439530b76b26e8833b69850 [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>
Patrick Venturefd6ba732019-10-31 14:27:39 -07007#include <functional>
James Feist6714a252018-09-10 15:26:18 -07008#include <iostream>
Patrick Venturefd6ba732019-10-31 14:27:39 -07009#include <memory>
James Feist6714a252018-09-10 15:26:18 -070010#include <regex>
11#include <sdbusplus/asio/connection.hpp>
James Feist82bac4c2019-03-11 11:16:53 -070012#include <sdbusplus/asio/object_server.hpp>
James Feist6714a252018-09-10 15:26:18 -070013#include <sdbusplus/message/types.hpp>
Patrick Venturefd6ba732019-10-31 14:27:39 -070014#include <string>
15#include <tuple>
16#include <utility>
17#include <variant>
18#include <vector>
James Feist6714a252018-09-10 15:26:18 -070019
James Feist58295ad2019-05-30 15:01:41 -070020constexpr const char* gpioPath = "/sys/class/gpio/";
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -070021const constexpr char* jsonStore = "/var/configuration/flattened.json";
22const constexpr char* inventoryPath = "/xyz/openbmc_project/inventory";
23const constexpr char* entityManagerName = "xyz.openbmc_project.EntityManager";
James Feist58295ad2019-05-30 15:01:41 -070024
25constexpr const char* cpuInventoryPath =
26 "/xyz/openbmc_project/inventory/system/chassis/motherboard";
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -070027const std::regex illegalDbusRegex("[^A-Za-z0-9_]");
James Feist6714a252018-09-10 15:26:18 -070028
29using BasicVariantType =
James Feist3eb82622019-02-08 13:10:22 -080030 std::variant<std::vector<std::string>, std::string, int64_t, uint64_t,
31 double, int32_t, uint32_t, int16_t, uint16_t, uint8_t, bool>;
James Feist6714a252018-09-10 15:26:18 -070032
33using ManagedObjectType = boost::container::flat_map<
34 sdbusplus::message::object_path,
35 boost::container::flat_map<
36 std::string,
37 boost::container::flat_map<std::string, BasicVariantType>>>;
38using SensorData = boost::container::flat_map<
39 std::string, boost::container::flat_map<std::string, BasicVariantType>>;
40
James Feista5e58722019-04-22 14:43:11 -070041using GetSubTreeType = std::vector<
42 std::pair<std::string,
43 std::vector<std::pair<std::string, std::vector<std::string>>>>>;
James Feist87d713a2018-12-06 16:06:24 -080044using SensorBaseConfiguration =
45 std::pair<std::string,
46 boost::container::flat_map<std::string, BasicVariantType>>;
47
James Feistd8bd5622019-06-26 12:09:05 -070048using Association = std::tuple<std::string, std::string, std::string>;
49
James Feistcf3bce62019-01-08 10:07:19 -080050bool findFiles(const std::filesystem::path dirPath,
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -070051 const std::string& matchString,
James Feistcf3bce62019-01-08 10:07:19 -080052 std::vector<std::filesystem::path>& foundPaths,
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -070053 unsigned int symlinkDepth = 1);
James Feist71d31b22019-01-02 16:57:54 -080054bool isPowerOn(void);
James Feistfc94b212019-02-06 16:14:51 -080055bool hasBiosPost(void);
James Feist71d31b22019-01-02 16:57:54 -080056void setupPowerMatch(const std::shared_ptr<sdbusplus::asio::connection>& conn);
James Feist6714a252018-09-10 15:26:18 -070057bool getSensorConfiguration(
58 const std::string& type,
59 const std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
James Feist87d713a2018-12-06 16:06:24 -080060 ManagedObjectType& resp, bool useCache = false);
61
James Feist82bac4c2019-03-11 11:16:53 -070062void createAssociation(
63 std::shared_ptr<sdbusplus::asio::dbus_interface>& association,
64 const std::string& path);
65
James Feist87d713a2018-12-06 16:06:24 -080066// replaces limits if MinReading and MaxReading are found.
67void findLimits(std::pair<double, double>& limits,
James Feist40a72142018-12-21 10:09:53 -080068 const SensorBaseConfiguration* data);
69
James Feistfc94b212019-02-06 16:14:51 -080070enum class PowerState
James Feist6ef20402019-01-07 16:45:08 -080071{
72 on,
James Feistfc94b212019-02-06 16:14:51 -080073 biosPost,
James Feist6ef20402019-01-07 16:45:08 -080074 always
75};
76
James Feista5e58722019-04-22 14:43:11 -070077namespace mapper
78{
79constexpr const char* busName = "xyz.openbmc_project.ObjectMapper";
80constexpr const char* path = "/xyz/openbmc_project/object_mapper";
81constexpr const char* interface = "xyz.openbmc_project.ObjectMapper";
82constexpr const char* subtree = "GetSubTree";
83} // namespace mapper
84
85namespace properties
86{
87constexpr const char* interface = "org.freedesktop.DBus.Properties";
88constexpr const char* get = "Get";
89} // namespace properties
90
James Feist52497fd2019-06-07 13:01:33 -070091namespace power
92{
93const static constexpr char* busname = "xyz.openbmc_project.State.Host";
94const static constexpr char* interface = "xyz.openbmc_project.State.Host";
95const static constexpr char* path = "/xyz/openbmc_project/state/host0";
96const static constexpr char* property = "CurrentHostState";
97} // namespace power
98namespace post
99{
100const static constexpr char* busname =
101 "xyz.openbmc_project.State.OperatingSystem";
102const static constexpr char* interface =
103 "xyz.openbmc_project.State.OperatingSystem.Status";
104const static constexpr char* path = "/xyz/openbmc_project/state/os";
105const static constexpr char* property = "OperatingSystemState";
106} // namespace post
107
James Feist2adc95c2019-09-30 14:55:28 -0700108namespace association
109{
110const static constexpr char* interface =
111 "xyz.openbmc_project.Association.Definitions";
112} // namespace association
113
James Feist40a72142018-12-21 10:09:53 -0800114template <typename T>
115inline T loadVariant(
116 const boost::container::flat_map<std::string, BasicVariantType>& data,
117 const std::string& key)
118{
119 auto it = data.find(key);
120 if (it == data.end())
121 {
122 std::cerr << "Configuration missing " << key << "\n";
123 throw std::invalid_argument("Key Missing");
124 }
125 if constexpr (std::is_same_v<T, double>)
126 {
James Feist3eb82622019-02-08 13:10:22 -0800127 return std::visit(VariantToDoubleVisitor(), it->second);
James Feist40a72142018-12-21 10:09:53 -0800128 }
James Feist6ef20402019-01-07 16:45:08 -0800129 else if constexpr (std::is_unsigned_v<T>)
130 {
James Feist3eb82622019-02-08 13:10:22 -0800131 return std::visit(VariantToUnsignedIntVisitor(), it->second);
James Feist6ef20402019-01-07 16:45:08 -0800132 }
James Feist40a72142018-12-21 10:09:53 -0800133 else if constexpr (std::is_same_v<T, std::string>)
134 {
James Feist3eb82622019-02-08 13:10:22 -0800135 return std::visit(VariantToStringVisitor(), it->second);
James Feist40a72142018-12-21 10:09:53 -0800136 }
137 else
138 {
James Feist52497fd2019-06-07 13:01:33 -0700139 static_assert(!std::is_same_v<T, T>, "Type Not Implemented");
James Feist40a72142018-12-21 10:09:53 -0800140 }
141}
James Feistfc94b212019-02-06 16:14:51 -0800142
143inline void setReadState(const std::string& str, PowerState& val)
144{
145
146 if (str == "On")
147 {
148 val = PowerState::on;
149 }
150 else if (str == "BiosPost")
151 {
152 val = PowerState::biosPost;
153 }
154 else if (str == "Always")
155 {
156 val = PowerState::always;
157 }
158}
Cheng C Yang5580f2f2019-09-19 09:01:47 +0800159
160void createInventoryAssoc(
161 std::shared_ptr<sdbusplus::asio::connection> conn,
162 std::shared_ptr<sdbusplus::asio::dbus_interface> association,
163 const std::string& path);
James Feistc71c1192019-09-18 14:31:33 -0700164
165struct GetSensorConfiguration
166 : std::enable_shared_from_this<GetSensorConfiguration>
167{
168 GetSensorConfiguration(
169 std::shared_ptr<sdbusplus::asio::connection> connection,
170 std::function<void(ManagedObjectType& resp)>&& callbackFunc) :
171 dbusConnection(connection),
172 callback(std::move(callbackFunc))
173 {
174 }
175 void getConfiguration(const std::vector<std::string>& interfaces)
176 {
177 std::shared_ptr<GetSensorConfiguration> self = shared_from_this();
178 dbusConnection->async_method_call(
179 [self, interfaces](const boost::system::error_code ec,
180 const GetSubTreeType& ret) {
181 if (ec)
182 {
183 std::cerr << "Error calling mapper\n";
184 return;
185 }
186 for (const auto& [path, objDict] : ret)
187 {
188 if (objDict.empty())
189 {
190 return;
191 }
192 const std::string& owner = objDict.begin()->first;
193
194 for (const std::string& interface : objDict.begin()->second)
195 {
196 // anything that starts with a requested configuration
197 // is good
198 if (std::find_if(
199 interfaces.begin(), interfaces.end(),
200 [interface](const std::string& possible) {
201 return boost::starts_with(interface,
202 possible);
203 }) == interfaces.end())
204 {
205 continue;
206 }
207
208 self->dbusConnection->async_method_call(
209 [self, path, interface](
210 const boost::system::error_code ec,
211 boost::container::flat_map<
212 std::string, BasicVariantType>& data) {
213 if (ec)
214 {
215 std::cerr << "Error getting " << path
216 << "\n";
217 return;
218 }
219 self->respData[path][interface] =
220 std::move(data);
221 },
222 owner, path, "org.freedesktop.DBus.Properties",
223 "GetAll", interface);
224 }
225 }
226 },
227 mapper::busName, mapper::path, mapper::interface, mapper::subtree,
228 "/", 0, interfaces);
229 }
230
231 ~GetSensorConfiguration()
232 {
233 callback(respData);
234 }
235
236 std::shared_ptr<sdbusplus::asio::connection> dbusConnection;
237 std::function<void(ManagedObjectType& resp)> callback;
238 ManagedObjectType respData;
239};