blob: da8cc67457843d4becd7cfd10a3deb2f8178bade [file] [log] [blame]
James Feist6714a252018-09-10 15:26:18 -07001/*
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
Bruce Lee1263c3d2021-06-04 15:16:33 +080017#include "dbus-sensor_config.h"
18
Ed Tanous8a57ec02020-10-09 12:46:52 -070019#include <Utils.hpp>
James Feist6714a252018-09-10 15:26:18 -070020#include <boost/algorithm/string/predicate.hpp>
Patrick Venture96e97db2019-10-31 13:44:38 -070021#include <boost/container/flat_map.hpp>
James Feist38fb5982020-05-28 10:09:54 -070022#include <sdbusplus/asio/connection.hpp>
23#include <sdbusplus/asio/object_server.hpp>
24#include <sdbusplus/bus/match.hpp>
25
James Feist24f02f22019-04-15 11:05:39 -070026#include <filesystem>
James Feist6714a252018-09-10 15:26:18 -070027#include <fstream>
Patrick Venture96e97db2019-10-31 13:44:38 -070028#include <memory>
James Feist6714a252018-09-10 15:26:18 -070029#include <regex>
Patrick Venture96e97db2019-10-31 13:44:38 -070030#include <stdexcept>
31#include <string>
32#include <utility>
33#include <variant>
34#include <vector>
James Feist6714a252018-09-10 15:26:18 -070035
James Feistcf3bce62019-01-08 10:07:19 -080036namespace fs = std::filesystem;
James Feist6714a252018-09-10 15:26:18 -070037
James Feist6ef20402019-01-07 16:45:08 -080038static bool powerStatusOn = false;
James Feistfc94b212019-02-06 16:14:51 -080039static bool biosHasPost = false;
Bruce Lee1263c3d2021-06-04 15:16:33 +080040static bool manufacturingMode = false;
James Feist58295ad2019-05-30 15:01:41 -070041
Patrick Williams92f8f512022-07-22 19:26:55 -050042static std::unique_ptr<sdbusplus::bus::match_t> powerMatch = nullptr;
43static std::unique_ptr<sdbusplus::bus::match_t> postMatch = nullptr;
James Feist71d31b22019-01-02 16:57:54 -080044
Jason Ling100c20b2020-08-11 14:50:33 -070045/**
46 * return the contents of a file
47 * @param[in] hwmonFile - the path to the file to read
48 * @return the contents of the file as a string or nullopt if the file could not
49 * be opened.
50 */
51
52std::optional<std::string> openAndRead(const std::string& hwmonFile)
53{
54 std::string fileVal;
55 std::ifstream fileStream(hwmonFile);
56 if (!fileStream.is_open())
57 {
58 return std::nullopt;
59 }
60 std::getline(fileStream, fileVal);
61 return fileVal;
62}
63
64/**
65 * given a hwmon temperature base name if valid return the full path else
66 * nullopt
67 * @param[in] directory - the hwmon sysfs directory
68 * @param[in] permitSet - a set of labels or hwmon basenames to permit. If this
69 * is empty then *everything* is permitted.
70 * @return a string to the full path of the file to create a temp sensor with or
71 * nullopt to indicate that no sensor should be created for this basename.
72 */
73std::optional<std::string>
74 getFullHwmonFilePath(const std::string& directory,
75 const std::string& hwmonBaseName,
76 const std::set<std::string>& permitSet)
77{
78 std::optional<std::string> result;
79 std::string filename;
80 if (permitSet.empty())
81 {
82 result = directory + "/" + hwmonBaseName + "_input";
83 return result;
84 }
85 filename = directory + "/" + hwmonBaseName + "_label";
86 auto searchVal = openAndRead(filename);
87 if (!searchVal)
88 {
89 /* if the hwmon temp doesn't have a corresponding label file
90 * then use the hwmon temperature base name
91 */
92 searchVal = hwmonBaseName;
93 }
94 if (permitSet.find(*searchVal) != permitSet.end())
95 {
96 result = directory + "/" + hwmonBaseName + "_input";
97 }
98 return result;
99}
100
101/**
102 * retrieve a set of basenames and labels to allow sensor creation for.
103 * @param[in] config - a map representing the configuration for a specific
104 * device
105 * @return a set of basenames and labels to allow sensor creation for. An empty
106 * set indicates that everything is permitted.
107 */
108std::set<std::string> getPermitSet(const SensorBaseConfigMap& config)
109{
110 auto permitAttribute = config.find("Labels");
111 std::set<std::string> permitSet;
112 if (permitAttribute != config.end())
113 {
114 try
115 {
116 auto val =
117 std::get<std::vector<std::string>>(permitAttribute->second);
118
119 permitSet.insert(std::make_move_iterator(val.begin()),
120 std::make_move_iterator(val.end()));
121 }
122 catch (const std::bad_variant_access& err)
123 {
124 std::cerr << err.what()
125 << ":PermitList does not contain a list, wrong "
126 "variant type.\n";
127 }
128 }
129 return permitSet;
130}
131
James Feist6714a252018-09-10 15:26:18 -0700132bool getSensorConfiguration(
133 const std::string& type,
134 const std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
Ed Tanous8a57ec02020-10-09 12:46:52 -0700135 ManagedObjectType& resp)
136{
137 return getSensorConfiguration(type, dbusConnection, resp, false);
138}
139
140bool getSensorConfiguration(
141 const std::string& type,
142 const std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
James Feist6714a252018-09-10 15:26:18 -0700143 ManagedObjectType& resp, bool useCache)
144{
145 static ManagedObjectType managedObj;
146
147 if (!useCache)
148 {
149 managedObj.clear();
Patrick Williams92f8f512022-07-22 19:26:55 -0500150 sdbusplus::message_t getManagedObjects =
James Feist6714a252018-09-10 15:26:18 -0700151 dbusConnection->new_method_call(
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -0700152 entityManagerName, "/", "org.freedesktop.DBus.ObjectManager",
James Feist6714a252018-09-10 15:26:18 -0700153 "GetManagedObjects");
154 bool err = false;
155 try
156 {
Patrick Williams92f8f512022-07-22 19:26:55 -0500157 sdbusplus::message_t reply =
James Feist6714a252018-09-10 15:26:18 -0700158 dbusConnection->call(getManagedObjects);
Yoo, Jae Hyun0e022052018-10-15 14:05:37 -0700159 reply.read(managedObj);
James Feist6714a252018-09-10 15:26:18 -0700160 }
Patrick Williams92f8f512022-07-22 19:26:55 -0500161 catch (const sdbusplus::exception_t& e)
James Feist6714a252018-09-10 15:26:18 -0700162 {
Jason Ling5747fab2019-10-02 16:46:23 -0700163 std::cerr << "While calling GetManagedObjects on service:"
164 << entityManagerName << " exception name:" << e.name()
165 << "and description:" << e.description()
166 << " was thrown\n";
James Feist6714a252018-09-10 15:26:18 -0700167 err = true;
168 }
169
170 if (err)
171 {
172 std::cerr << "Error communicating to entity manager\n";
173 return false;
174 }
175 }
176 for (const auto& pathPair : managedObj)
177 {
James Feist6714a252018-09-10 15:26:18 -0700178 bool correctType = false;
179 for (const auto& entry : pathPair.second)
180 {
181 if (boost::starts_with(entry.first, type))
182 {
183 correctType = true;
184 break;
185 }
186 }
187 if (correctType)
188 {
189 resp.emplace(pathPair);
190 }
191 }
192 return true;
193}
194
Lei YU6a4e9732021-10-20 13:27:34 +0800195bool findFiles(const fs::path& dirPath, std::string_view matchString,
Ed Tanous8a57ec02020-10-09 12:46:52 -0700196 std::vector<fs::path>& foundPaths, int symlinkDepth)
James Feist6714a252018-09-10 15:26:18 -0700197{
Lei YU6a4e9732021-10-20 13:27:34 +0800198 std::error_code ec;
199 if (!fs::exists(dirPath, ec))
Ed Tanous8a57ec02020-10-09 12:46:52 -0700200 {
James Feist6714a252018-09-10 15:26:18 -0700201 return false;
Ed Tanous8a57ec02020-10-09 12:46:52 -0700202 }
James Feist6714a252018-09-10 15:26:18 -0700203
Lei YU6a4e9732021-10-20 13:27:34 +0800204 std::vector<std::regex> matchPieces;
205
206 size_t pos = 0;
207 std::string token;
208 // Generate the regex expressions list from the match we were given
209 while ((pos = matchString.find('/')) != std::string::npos)
210 {
211 token = matchString.substr(0, pos);
212 matchPieces.emplace_back(token);
213 matchString.remove_prefix(pos + 1);
214 }
215 matchPieces.emplace_back(std::string{matchString});
216
217 // Check if the match string contains directories, and skip the match of
218 // subdirectory if not
219 if (matchPieces.size() <= 1)
220 {
221 std::regex search(std::string{matchString});
222 std::smatch match;
223 for (auto p = fs::recursive_directory_iterator(
224 dirPath, fs::directory_options::follow_directory_symlink);
225 p != fs::recursive_directory_iterator(); ++p)
226 {
227 std::string path = p->path().string();
228 if (!is_directory(*p))
229 {
230 if (std::regex_search(path, match, search))
231 {
232 foundPaths.emplace_back(p->path());
233 }
234 }
235 if (p.depth() >= symlinkDepth)
236 {
237 p.disable_recursion_pending();
238 }
239 }
240 return true;
241 }
242
243 // The match string contains directories, verify each level of sub
244 // directories
Ed Tanous8a57ec02020-10-09 12:46:52 -0700245 for (auto p = fs::recursive_directory_iterator(
246 dirPath, fs::directory_options::follow_directory_symlink);
247 p != fs::recursive_directory_iterator(); ++p)
James Feist6714a252018-09-10 15:26:18 -0700248 {
Lei YU6a4e9732021-10-20 13:27:34 +0800249 std::vector<std::regex>::iterator matchPiece = matchPieces.begin();
250 fs::path::iterator pathIt = p->path().begin();
251 for (const fs::path& dir : dirPath)
252 {
253 if (dir.empty())
254 {
255 // When the path ends with '/', it gets am empty path
256 // skip such case.
257 break;
258 }
259 pathIt++;
260 }
261
262 while (pathIt != p->path().end())
263 {
264 // Found a path deeper than match.
265 if (matchPiece == matchPieces.end())
266 {
267 p.disable_recursion_pending();
268 break;
269 }
270 std::smatch match;
271 std::string component = pathIt->string();
272 std::regex regexPiece(*matchPiece);
273 if (!std::regex_match(component, match, regexPiece))
274 {
275 // path prefix doesn't match, no need to iterate further
276 p.disable_recursion_pending();
277 break;
278 }
279 matchPiece++;
280 pathIt++;
281 }
282
Ed Tanous8a57ec02020-10-09 12:46:52 -0700283 if (!is_directory(*p))
James Feist6714a252018-09-10 15:26:18 -0700284 {
Lei YU6a4e9732021-10-20 13:27:34 +0800285 if (matchPiece == matchPieces.end())
Ed Tanous8a57ec02020-10-09 12:46:52 -0700286 {
287 foundPaths.emplace_back(p->path());
288 }
James Feist6714a252018-09-10 15:26:18 -0700289 }
Lei YU6a4e9732021-10-20 13:27:34 +0800290
Ed Tanous8a57ec02020-10-09 12:46:52 -0700291 if (p.depth() >= symlinkDepth)
James Feist6714a252018-09-10 15:26:18 -0700292 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700293 p.disable_recursion_pending();
James Feist6714a252018-09-10 15:26:18 -0700294 }
295 }
296 return true;
297}
298
James Feist71d31b22019-01-02 16:57:54 -0800299bool isPowerOn(void)
James Feist6714a252018-09-10 15:26:18 -0700300{
James Feist71d31b22019-01-02 16:57:54 -0800301 if (!powerMatch)
James Feist6714a252018-09-10 15:26:18 -0700302 {
James Feist71d31b22019-01-02 16:57:54 -0800303 throw std::runtime_error("Power Match Not Created");
James Feist6714a252018-09-10 15:26:18 -0700304 }
James Feist71d31b22019-01-02 16:57:54 -0800305 return powerStatusOn;
306}
307
James Feistfc94b212019-02-06 16:14:51 -0800308bool hasBiosPost(void)
309{
James Feist52497fd2019-06-07 13:01:33 -0700310 if (!postMatch)
James Feistfc94b212019-02-06 16:14:51 -0800311 {
James Feist52497fd2019-06-07 13:01:33 -0700312 throw std::runtime_error("Post Match Not Created");
James Feistfc94b212019-02-06 16:14:51 -0800313 }
314 return biosHasPost;
315}
316
Konstantin Aladyshevc7a1ae62021-04-30 08:50:43 +0000317bool readingStateGood(const PowerState& powerState)
318{
319 if (powerState == PowerState::on && !isPowerOn())
320 {
321 return false;
322 }
323 if (powerState == PowerState::biosPost && (!hasBiosPost() || !isPowerOn()))
324 {
325 return false;
326 }
327
328 return true;
329}
330
James Feist8aeffd92020-09-14 12:08:28 -0700331static void
332 getPowerStatus(const std::shared_ptr<sdbusplus::asio::connection>& conn,
333 size_t retries = 2)
334{
335 conn->async_method_call(
336 [conn, retries](boost::system::error_code ec,
337 const std::variant<std::string>& state) {
Ed Tanousbb679322022-05-16 16:10:00 -0700338 if (ec)
339 {
Ed Tanous2049bd22022-07-09 07:20:26 -0700340 if (retries != 0U)
James Feist8aeffd92020-09-14 12:08:28 -0700341 {
Ed Tanousbb679322022-05-16 16:10:00 -0700342 auto timer = std::make_shared<boost::asio::steady_timer>(
343 conn->get_io_context());
344 timer->expires_after(std::chrono::seconds(15));
345 timer->async_wait(
346 [timer, conn, retries](boost::system::error_code) {
347 getPowerStatus(conn, retries - 1);
348 });
James Feist8aeffd92020-09-14 12:08:28 -0700349 return;
350 }
Ed Tanousbb679322022-05-16 16:10:00 -0700351
352 // we commonly come up before power control, we'll capture the
353 // property change later
354 std::cerr << "error getting power status " << ec.message() << "\n";
355 return;
356 }
357 powerStatusOn =
358 boost::ends_with(std::get<std::string>(state), ".Running");
James Feist8aeffd92020-09-14 12:08:28 -0700359 },
360 power::busname, power::path, properties::interface, properties::get,
361 power::interface, power::property);
362}
363
364static void
365 getPostStatus(const std::shared_ptr<sdbusplus::asio::connection>& conn,
366 size_t retries = 2)
367{
368 conn->async_method_call(
369 [conn, retries](boost::system::error_code ec,
370 const std::variant<std::string>& state) {
Ed Tanousbb679322022-05-16 16:10:00 -0700371 if (ec)
372 {
Ed Tanous2049bd22022-07-09 07:20:26 -0700373 if (retries != 0U)
James Feist8aeffd92020-09-14 12:08:28 -0700374 {
Ed Tanousbb679322022-05-16 16:10:00 -0700375 auto timer = std::make_shared<boost::asio::steady_timer>(
376 conn->get_io_context());
377 timer->expires_after(std::chrono::seconds(15));
378 timer->async_wait(
379 [timer, conn, retries](boost::system::error_code) {
380 getPostStatus(conn, retries - 1);
381 });
James Feist8aeffd92020-09-14 12:08:28 -0700382 return;
383 }
Ed Tanousbb679322022-05-16 16:10:00 -0700384 // we commonly come up before power control, we'll capture the
385 // property change later
386 std::cerr << "error getting post status " << ec.message() << "\n";
387 return;
388 }
Ed Tanous2049bd22022-07-09 07:20:26 -0700389 const auto& value = std::get<std::string>(state);
Ed Tanousbb679322022-05-16 16:10:00 -0700390 biosHasPost = (value != "Inactive") &&
391 (value != "xyz.openbmc_project.State.OperatingSystem."
392 "Status.OSStatus.Inactive");
James Feist8aeffd92020-09-14 12:08:28 -0700393 },
394 post::busname, post::path, properties::interface, properties::get,
395 post::interface, post::property);
396}
397
James Feist71d31b22019-01-02 16:57:54 -0800398void setupPowerMatch(const std::shared_ptr<sdbusplus::asio::connection>& conn)
399{
James Feist43d32fe2019-09-04 10:35:20 -0700400 static boost::asio::steady_timer timer(conn->get_io_context());
James Feist6714a252018-09-10 15:26:18 -0700401 // create a match for powergood changes, first time do a method call to
James Feist71d31b22019-01-02 16:57:54 -0800402 // cache the correct value
James Feist52497fd2019-06-07 13:01:33 -0700403 if (powerMatch)
404 {
405 return;
406 }
James Feist6714a252018-09-10 15:26:18 -0700407
Patrick Williams92f8f512022-07-22 19:26:55 -0500408 powerMatch = std::make_unique<sdbusplus::bus::match_t>(
409 static_cast<sdbusplus::bus_t&>(*conn),
James Feist52497fd2019-06-07 13:01:33 -0700410 "type='signal',interface='" + std::string(properties::interface) +
411 "',path='" + std::string(power::path) + "',arg0='" +
412 std::string(power::interface) + "'",
Patrick Williams92f8f512022-07-22 19:26:55 -0500413 [](sdbusplus::message_t& message) {
Ed Tanousbb679322022-05-16 16:10:00 -0700414 std::string objectName;
415 boost::container::flat_map<std::string, std::variant<std::string>>
416 values;
417 message.read(objectName, values);
418 auto findState = values.find(power::property);
419 if (findState != values.end())
420 {
421 bool on = boost::ends_with(std::get<std::string>(findState->second),
422 ".Running");
423 if (!on)
James Feist6714a252018-09-10 15:26:18 -0700424 {
Ed Tanousbb679322022-05-16 16:10:00 -0700425 timer.cancel();
426 powerStatusOn = false;
427 return;
428 }
429 // on comes too quickly
430 timer.expires_after(std::chrono::seconds(10));
431 timer.async_wait([](boost::system::error_code ec) {
432 if (ec == boost::asio::error::operation_aborted)
James Feist43d32fe2019-09-04 10:35:20 -0700433 {
James Feist43d32fe2019-09-04 10:35:20 -0700434 return;
435 }
Ed Tanousbb679322022-05-16 16:10:00 -0700436 if (ec)
437 {
438 std::cerr << "Timer error " << ec.message() << "\n";
439 return;
440 }
441 powerStatusOn = true;
442 });
443 }
James Feist52497fd2019-06-07 13:01:33 -0700444 });
445
Patrick Williams92f8f512022-07-22 19:26:55 -0500446 postMatch = std::make_unique<sdbusplus::bus::match_t>(
447 static_cast<sdbusplus::bus_t&>(*conn),
James Feist52497fd2019-06-07 13:01:33 -0700448 "type='signal',interface='" + std::string(properties::interface) +
449 "',path='" + std::string(post::path) + "',arg0='" +
450 std::string(post::interface) + "'",
Patrick Williams92f8f512022-07-22 19:26:55 -0500451 [](sdbusplus::message_t& message) {
Ed Tanousbb679322022-05-16 16:10:00 -0700452 std::string objectName;
453 boost::container::flat_map<std::string, std::variant<std::string>>
454 values;
455 message.read(objectName, values);
456 auto findState = values.find(post::property);
457 if (findState != values.end())
458 {
459 auto& value = std::get<std::string>(findState->second);
460 biosHasPost = (value != "Inactive") &&
461 (value != "xyz.openbmc_project.State.OperatingSystem."
462 "Status.OSStatus.Inactive");
463 }
James Feist52497fd2019-06-07 13:01:33 -0700464 });
James Feistfc94b212019-02-06 16:14:51 -0800465
James Feist8aeffd92020-09-14 12:08:28 -0700466 getPowerStatus(conn);
467 getPostStatus(conn);
James Feist3f0e8762018-11-27 11:30:42 -0800468}
James Feist87d713a2018-12-06 16:06:24 -0800469
470// replaces limits if MinReading and MaxReading are found.
471void findLimits(std::pair<double, double>& limits,
472 const SensorBaseConfiguration* data)
473{
Ed Tanous2049bd22022-07-09 07:20:26 -0700474 if (data == nullptr)
James Feist87d713a2018-12-06 16:06:24 -0800475 {
476 return;
477 }
478 auto maxFind = data->second.find("MaxReading");
479 auto minFind = data->second.find("MinReading");
480
481 if (minFind != data->second.end())
482 {
James Feist3eb82622019-02-08 13:10:22 -0800483 limits.first = std::visit(VariantToDoubleVisitor(), minFind->second);
James Feist87d713a2018-12-06 16:06:24 -0800484 }
485 if (maxFind != data->second.end())
486 {
James Feist3eb82622019-02-08 13:10:22 -0800487 limits.second = std::visit(VariantToDoubleVisitor(), maxFind->second);
James Feist87d713a2018-12-06 16:06:24 -0800488 }
James Feistfc94b212019-02-06 16:14:51 -0800489}
James Feist82bac4c2019-03-11 11:16:53 -0700490
491void createAssociation(
492 std::shared_ptr<sdbusplus::asio::dbus_interface>& association,
493 const std::string& path)
494{
495 if (association)
496 {
Lei YU6a4e9732021-10-20 13:27:34 +0800497 fs::path p(path);
James Feistd2543f82019-04-09 11:10:06 -0700498
James Feist82bac4c2019-03-11 11:16:53 -0700499 std::vector<Association> associations;
Ed Tanous8a57ec02020-10-09 12:46:52 -0700500 associations.emplace_back("chassis", "all_sensors",
501 p.parent_path().string());
James Feist2adc95c2019-09-30 14:55:28 -0700502 association->register_property("Associations", associations);
James Feist82bac4c2019-03-11 11:16:53 -0700503 association->initialize();
504 }
James Feist43d32fe2019-09-04 10:35:20 -0700505}
Cheng C Yang5580f2f2019-09-19 09:01:47 +0800506
507void setInventoryAssociation(
Ed Tanous8a57ec02020-10-09 12:46:52 -0700508 const std::shared_ptr<sdbusplus::asio::dbus_interface>& association,
AppaRao Pulic82213c2020-02-27 01:24:58 +0530509 const std::string& path,
510 const std::vector<std::string>& chassisPaths = std::vector<std::string>())
Cheng C Yang5580f2f2019-09-19 09:01:47 +0800511{
512 if (association)
513 {
Lei YU6a4e9732021-10-20 13:27:34 +0800514 fs::path p(path);
Cheng C Yang5580f2f2019-09-19 09:01:47 +0800515 std::vector<Association> associations;
AppaRao Pulic82213c2020-02-27 01:24:58 +0530516 std::string objPath(p.parent_path().string());
517
Ed Tanous8a57ec02020-10-09 12:46:52 -0700518 associations.emplace_back("inventory", "sensors", objPath);
519 associations.emplace_back("chassis", "all_sensors", objPath);
AppaRao Pulic82213c2020-02-27 01:24:58 +0530520
521 for (const std::string& chassisPath : chassisPaths)
522 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700523 associations.emplace_back("chassis", "all_sensors", chassisPath);
AppaRao Pulic82213c2020-02-27 01:24:58 +0530524 }
525
James Feist2adc95c2019-09-30 14:55:28 -0700526 association->register_property("Associations", associations);
Cheng C Yang5580f2f2019-09-19 09:01:47 +0800527 association->initialize();
528 }
529}
530
531void createInventoryAssoc(
Ed Tanous8a57ec02020-10-09 12:46:52 -0700532 const std::shared_ptr<sdbusplus::asio::connection>& conn,
533 const std::shared_ptr<sdbusplus::asio::dbus_interface>& association,
Cheng C Yang5580f2f2019-09-19 09:01:47 +0800534 const std::string& path)
535{
536 if (!association)
537 {
538 return;
539 }
AppaRao Pulic82213c2020-02-27 01:24:58 +0530540
Cheng C Yang5580f2f2019-09-19 09:01:47 +0800541 conn->async_method_call(
542 [association, path](const boost::system::error_code ec,
AppaRao Pulic82213c2020-02-27 01:24:58 +0530543 const std::vector<std::string>& invSysObjPaths) {
Ed Tanousbb679322022-05-16 16:10:00 -0700544 if (ec)
545 {
546 // In case of error, set the default associations and
547 // initialize the association Interface.
548 setInventoryAssociation(association, path);
549 return;
550 }
551 setInventoryAssociation(association, path, invSysObjPaths);
Cheng C Yang5580f2f2019-09-19 09:01:47 +0800552 },
553 mapper::busName, mapper::path, mapper::interface, "GetSubTreePaths",
554 "/xyz/openbmc_project/inventory/system", 2,
555 std::array<std::string, 1>{
556 "xyz.openbmc_project.Inventory.Item.System"});
557}
Zbigniew Kurzynski63f38662020-06-09 13:02:11 +0200558
559std::optional<double> readFile(const std::string& thresholdFile,
560 const double& scaleFactor)
561{
562 std::string line;
563 std::ifstream labelFile(thresholdFile);
564 if (labelFile.good())
565 {
566 std::getline(labelFile, line);
567 labelFile.close();
568
569 try
570 {
571 return std::stod(line) / scaleFactor;
572 }
573 catch (const std::invalid_argument&)
574 {
575 return std::nullopt;
576 }
577 }
578 return std::nullopt;
579}
580
581std::optional<std::tuple<std::string, std::string, std::string>>
Lei YU6a4e9732021-10-20 13:27:34 +0800582 splitFileName(const fs::path& filePath)
Zbigniew Kurzynski63f38662020-06-09 13:02:11 +0200583{
584 if (filePath.has_filename())
585 {
586 const auto fileName = filePath.filename().string();
Zbigniew Kurzynski63f38662020-06-09 13:02:11 +0200587
Zbigniew Kurzynskidd648002020-07-10 16:44:16 +0200588 size_t numberPos = std::strcspn(fileName.c_str(), "1234567890");
589 size_t itemPos = std::strcspn(fileName.c_str(), "_");
590
591 if (numberPos > 0 && itemPos > numberPos && fileName.size() > itemPos)
Zbigniew Kurzynski63f38662020-06-09 13:02:11 +0200592 {
Zbigniew Kurzynskidd648002020-07-10 16:44:16 +0200593 return std::make_optional(
594 std::make_tuple(fileName.substr(0, numberPos),
595 fileName.substr(numberPos, itemPos - numberPos),
596 fileName.substr(itemPos + 1, fileName.size())));
Zbigniew Kurzynski63f38662020-06-09 13:02:11 +0200597 }
598 }
599 return std::nullopt;
Zbigniew Kurzynskidd648002020-07-10 16:44:16 +0200600}
Bruce Lee1263c3d2021-06-04 15:16:33 +0800601
Arun P. Mohanan45f844a2021-11-03 22:18:09 +0530602static void handleSpecialModeChange(const std::string& manufacturingModeStatus)
603{
604 manufacturingMode = false;
605 if (manufacturingModeStatus == "xyz.openbmc_project.Control.Security."
606 "SpecialMode.Modes.Manufacturing")
607 {
608 manufacturingMode = true;
609 }
Ed Tanous74cffa82022-01-25 13:00:28 -0800610 if (validateUnsecureFeature == 1)
Arun P. Mohanan45f844a2021-11-03 22:18:09 +0530611 {
612 if (manufacturingModeStatus == "xyz.openbmc_project.Control.Security."
613 "SpecialMode.Modes.ValidationUnsecure")
614 {
615 manufacturingMode = true;
616 }
617 }
618}
619
Bruce Lee1263c3d2021-06-04 15:16:33 +0800620void setupManufacturingModeMatch(sdbusplus::asio::connection& conn)
621{
Arun P. Mohanan45f844a2021-11-03 22:18:09 +0530622 namespace rules = sdbusplus::bus::match::rules;
623 static constexpr const char* specialModeInterface =
624 "xyz.openbmc_project.Security.SpecialMode";
625
626 const std::string filterSpecialModeIntfAdd =
627 rules::interfacesAdded() +
628 rules::argNpath(0, "/xyz/openbmc_project/security/special_mode");
Patrick Williams92f8f512022-07-22 19:26:55 -0500629 static std::unique_ptr<sdbusplus::bus::match_t> specialModeIntfMatch =
630 std::make_unique<sdbusplus::bus::match_t>(conn,
631 filterSpecialModeIntfAdd,
632 [](sdbusplus::message_t& m) {
Ed Tanousbb679322022-05-16 16:10:00 -0700633 sdbusplus::message::object_path path;
634 using PropertyMap =
635 boost::container::flat_map<std::string, std::variant<std::string>>;
636 boost::container::flat_map<std::string, PropertyMap> interfaceAdded;
637 m.read(path, interfaceAdded);
638 auto intfItr = interfaceAdded.find(specialModeInterface);
639 if (intfItr == interfaceAdded.end())
640 {
641 return;
642 }
643 PropertyMap& propertyList = intfItr->second;
644 auto itr = propertyList.find("SpecialMode");
645 if (itr == propertyList.end())
646 {
647 std::cerr << "error getting SpecialMode property "
648 << "\n";
649 return;
650 }
Ed Tanous2049bd22022-07-09 07:20:26 -0700651 auto* manufacturingModeStatus = std::get_if<std::string>(&itr->second);
Ed Tanousbb679322022-05-16 16:10:00 -0700652 handleSpecialModeChange(*manufacturingModeStatus);
Patrick Williams92f8f512022-07-22 19:26:55 -0500653 });
Bruce Lee1263c3d2021-06-04 15:16:33 +0800654
Arun P. Mohanan45f844a2021-11-03 22:18:09 +0530655 const std::string filterSpecialModeChange =
656 rules::type::signal() + rules::member("PropertiesChanged") +
657 rules::interface("org.freedesktop.DBus.Properties") +
658 rules::argN(0, specialModeInterface);
Patrick Williams92f8f512022-07-22 19:26:55 -0500659 static std::unique_ptr<sdbusplus::bus::match_t> specialModeChangeMatch =
660 std::make_unique<sdbusplus::bus::match_t>(conn, filterSpecialModeChange,
661 [](sdbusplus::message_t& m) {
Ed Tanousbb679322022-05-16 16:10:00 -0700662 std::string interfaceName;
663 boost::container::flat_map<std::string, std::variant<std::string>>
664 propertiesChanged;
Bruce Lee1263c3d2021-06-04 15:16:33 +0800665
Ed Tanousbb679322022-05-16 16:10:00 -0700666 m.read(interfaceName, propertiesChanged);
667 auto itr = propertiesChanged.find("SpecialMode");
668 if (itr == propertiesChanged.end())
669 {
670 return;
671 }
Ed Tanous2049bd22022-07-09 07:20:26 -0700672 auto* manufacturingModeStatus = std::get_if<std::string>(&itr->second);
Ed Tanousbb679322022-05-16 16:10:00 -0700673 handleSpecialModeChange(*manufacturingModeStatus);
Patrick Williams92f8f512022-07-22 19:26:55 -0500674 });
Bruce Lee1263c3d2021-06-04 15:16:33 +0800675
Arun P. Mohanan45f844a2021-11-03 22:18:09 +0530676 conn.async_method_call(
677 [](const boost::system::error_code ec,
678 const std::variant<std::string>& getManufactMode) {
Ed Tanousbb679322022-05-16 16:10:00 -0700679 if (ec)
680 {
681 std::cerr << "error getting SpecialMode status " << ec.message()
682 << "\n";
683 return;
684 }
Ed Tanous2049bd22022-07-09 07:20:26 -0700685 const auto* manufacturingModeStatus =
Ed Tanousbb679322022-05-16 16:10:00 -0700686 std::get_if<std::string>(&getManufactMode);
687 handleSpecialModeChange(*manufacturingModeStatus);
Arun P. Mohanan45f844a2021-11-03 22:18:09 +0530688 },
689 "xyz.openbmc_project.SpecialMode",
690 "/xyz/openbmc_project/security/special_mode",
691 "org.freedesktop.DBus.Properties", "Get", specialModeInterface,
692 "SpecialMode");
Bruce Lee1263c3d2021-06-04 15:16:33 +0800693}
694
695bool getManufacturingMode()
696{
697 return manufacturingMode;
Konstantin Aladyshevc7a1ae62021-04-30 08:50:43 +0000698}