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 /// \file utils.hpp
17
18 #pragma once
19
20 #include <boost/container/flat_map.hpp>
21 #include <nlohmann/json.hpp>
22 #include <sdbusplus/asio/connection.hpp>
23 #include <sdbusplus/exception.hpp>
24
25 #include <filesystem>
26 #include <fstream>
27 #include <iostream>
28
29 constexpr const char* configurationOutDir = "/var/configuration/";
30 constexpr const char* versionHashFile = "/var/configuration/version";
31 constexpr const char* versionFile = "/etc/os-release";
32
33 // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
34 extern boost::asio::io_context io;
35
36 using DBusValueVariant =
37 std::variant<std::string, int64_t, uint64_t, double, int32_t, uint32_t,
38 int16_t, uint16_t, uint8_t, bool, std::vector<uint8_t>>;
39 using DBusInterface = boost::container::flat_map<std::string, DBusValueVariant>;
40 using DBusObject = boost::container::flat_map<std::string, DBusInterface>;
41 using MapperGetSubTreeResponse =
42 boost::container::flat_map<std::string, DBusObject>;
43
44 namespace properties
45 {
46 constexpr const char* interface = "org.freedesktop.DBus.Properties";
47 constexpr const char* get = "Get";
48 } // namespace properties
49
50 namespace power
51 {
52 const static constexpr char* busname = "xyz.openbmc_project.State.Host";
53 const static constexpr char* interface = "xyz.openbmc_project.State.Host";
54 const static constexpr char* path = "/xyz/openbmc_project/state/host0";
55 const static constexpr char* property = "CurrentHostState";
56 } // namespace power
57
58 bool findFiles(const std::filesystem::path& dirPath,
59 const std::string& matchString,
60 std::vector<std::filesystem::path>& foundPaths);
61 bool findFiles(const std::vector<std::filesystem::path>&& dirPaths,
62 const std::string& matchString,
63 std::vector<std::filesystem::path>& foundPaths);
64
65 bool getI2cDevicePaths(
66 const std::filesystem::path& dirPath,
67 boost::container::flat_map<size_t, std::filesystem::path>& busPaths);
68
69 bool validateJson(const nlohmann::json& schemaFile,
70 const nlohmann::json& input);
71
72 bool isPowerOn();
73 void setupPowerMatch(const std::shared_ptr<sdbusplus::asio::connection>& conn);
74 struct DBusInternalError final : public sdbusplus::exception_t
75 {
nameDBusInternalError76 const char* name() const noexcept override
77 {
78 return "org.freedesktop.DBus.Error.Failed";
79 }
descriptionDBusInternalError80 const char* description() const noexcept override
81 {
82 return "internal error";
83 }
whatDBusInternalError84 const char* what() const noexcept override
85 {
86 return "org.freedesktop.DBus.Error.Failed: "
87 "internal error";
88 }
89
get_errnoDBusInternalError90 int get_errno() const noexcept override
91 {
92 return EACCES;
93 }
94 };
95
fwVersionIsSame()96 inline bool fwVersionIsSame()
97 {
98 std::ifstream version(versionFile);
99 if (!version.good())
100 {
101 std::cerr << "Can't read " << versionFile << "\n";
102 return false;
103 }
104
105 std::string versionData;
106 std::string line;
107 while (std::getline(version, line))
108 {
109 versionData += line;
110 }
111
112 std::string expectedHash =
113 std::to_string(std::hash<std::string>{}(versionData));
114
115 std::filesystem::create_directory(configurationOutDir);
116 std::ifstream hashFile(versionHashFile);
117 if (hashFile.good())
118 {
119 std::string hashString;
120 hashFile >> hashString;
121
122 if (expectedHash == hashString)
123 {
124 return true;
125 }
126 hashFile.close();
127 }
128
129 std::ofstream output(versionHashFile);
130 output << expectedHash;
131 return false;
132 }
133
134 std::optional<std::string> templateCharReplace(
135 nlohmann::json::iterator& keyPair, const DBusObject& object, size_t index,
136 const std::optional<std::string>& replaceStr = std::nullopt);
137
138 std::optional<std::string> templateCharReplace(
139 nlohmann::json::iterator& keyPair, const DBusInterface& interface,
140 size_t index, const std::optional<std::string>& replaceStr = std::nullopt);
141
deviceHasLogging(const nlohmann::json & json)142 inline bool deviceHasLogging(const nlohmann::json& json)
143 {
144 auto logging = json.find("Logging");
145 if (logging != json.end())
146 {
147 const auto* ptr = logging->get_ptr<const std::string*>();
148 if (ptr != nullptr)
149 {
150 if (*ptr == "Off")
151 {
152 return false;
153 }
154 }
155 }
156 return true;
157 }
158
159 /// \brief Match a Dbus property against a probe statement.
160 /// \param probe the probe statement to match against.
161 /// \param dbusValue the property value being matched to a probe.
162 /// \return true if the dbusValue matched the probe otherwise false.
163 bool matchProbe(const nlohmann::json& probe, const DBusValueVariant& dbusValue);
164