blob: 56469dda21e916c70473d5a0e32f3c0abb1d11d1 [file] [log] [blame]
Feist, Jamesc95cf672019-08-29 16:10:35 -07001/*
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 "utils.hpp"
18
19#include <boost/algorithm/string/replace.hpp>
20#include <boost/asio/steady_timer.hpp>
James Feist0b236ab2019-10-02 09:09:16 -070021#include <filesystem>
Feist, Jamesc95cf672019-08-29 16:10:35 -070022#include <iostream>
23#include <sdbusplus/asio/connection.hpp>
24#include <sdbusplus/asio/object_server.hpp>
25#include <sdbusplus/bus/match.hpp>
26#include <string>
James Feist45772222019-09-27 10:38:08 -070027#include <utility>
Feist, Jamesc95cf672019-08-29 16:10:35 -070028
29extern "C" {
30#include <i2c/smbus.h>
31#include <linux/i2c-dev.h>
32}
33
34constexpr const char* configType =
35 "xyz.openbmc_project.Configuration.Intel_HSBP_CPLD";
36
James Feist45772222019-09-27 10:38:08 -070037constexpr size_t scanRateSeconds = 5;
38constexpr size_t maxDrives = 8; // only 1 byte alloted
39
Feist, Jamesc95cf672019-08-29 16:10:35 -070040boost::asio::io_context io;
41auto conn = std::make_shared<sdbusplus::asio::connection>(io);
42sdbusplus::asio::object_server objServer(conn);
43
James Feist45772222019-09-27 10:38:08 -070044static std::string zeroPad(const uint8_t val)
45{
46 std::ostringstream version;
47 version << std::setw(2) << std::setfill('0') << static_cast<size_t>(val);
48 return version.str();
49}
50
James Feist0b236ab2019-10-02 09:09:16 -070051struct Mux
52{
53 Mux(size_t busIn, size_t addressIn) : bus(busIn), address(addressIn)
54 {
55 }
56 size_t bus;
57 size_t address;
58};
James Feist45772222019-09-27 10:38:08 -070059struct Drive
60{
James Feist244f3232019-09-27 15:15:14 -070061 Drive(size_t driveIndex, bool isPresent, bool isOperational, bool nvme,
62 bool rebuilding) :
James Feist45772222019-09-27 10:38:08 -070063 isNvme(nvme)
64 {
65 constexpr const char* basePath =
66 "/xyz/openbmc_project/inventory/item/drive/Drive_";
67 itemIface = objServer.add_interface(
68 basePath + std::to_string(driveIndex), inventory::interface);
69 itemIface->register_property("Present", isPresent);
70 itemIface->register_property("PrettyName",
71 "Drive " + std::to_string(driveIndex));
72 itemIface->initialize();
73 operationalIface = objServer.add_interface(
James Feist244f3232019-09-27 15:15:14 -070074 itemIface->get_object_path(),
James Feist45772222019-09-27 10:38:08 -070075 "xyz.openbmc_project.State.Decorator.OperationalStatus");
76 operationalIface->register_property("Functional", isOperational);
77 operationalIface->initialize();
James Feist244f3232019-09-27 15:15:14 -070078 rebuildingIface = objServer.add_interface(
79 itemIface->get_object_path(), "xyz.openbmc_project.State.Drive");
80 rebuildingIface->register_property("Rebuilding", rebuilding);
81 rebuildingIface->initialize();
James Feist45772222019-09-27 10:38:08 -070082 }
83 ~Drive()
84 {
85 objServer.remove_interface(itemIface);
86 objServer.remove_interface(operationalIface);
James Feist244f3232019-09-27 15:15:14 -070087 objServer.remove_interface(rebuildingIface);
James Feist0b236ab2019-10-02 09:09:16 -070088 objServer.remove_interface(associationIface);
89 }
90
91 void createAssociation(const std::string& path)
92 {
93 if (associationIface != nullptr)
94 {
95 return;
96 }
97 associationIface = objServer.add_interface(
98 itemIface->get_object_path(),
99 "xyz.openbmc_project.Association.Definitions");
100 std::vector<Association> associations;
101 associations.emplace_back("inventory", "drive", path);
102 associationIface->register_property("Associations", associations);
103 associationIface->initialize();
James Feist45772222019-09-27 10:38:08 -0700104 }
105
106 std::shared_ptr<sdbusplus::asio::dbus_interface> itemIface;
107 std::shared_ptr<sdbusplus::asio::dbus_interface> operationalIface;
James Feist244f3232019-09-27 15:15:14 -0700108 std::shared_ptr<sdbusplus::asio::dbus_interface> rebuildingIface;
James Feist0b236ab2019-10-02 09:09:16 -0700109 std::shared_ptr<sdbusplus::asio::dbus_interface> associationIface;
James Feist45772222019-09-27 10:38:08 -0700110 bool isNvme;
111};
112
Feist, Jamesc95cf672019-08-29 16:10:35 -0700113struct Backplane
114{
115
James Feist45772222019-09-27 10:38:08 -0700116 Backplane(size_t busIn, size_t addressIn, size_t backplaneIndexIn,
117 const std::string& nameIn) :
118 bus(busIn),
119 address(addressIn), backplaneIndex(backplaneIndexIn - 1), name(nameIn),
James Feist0b236ab2019-10-02 09:09:16 -0700120 timer(std::make_shared<boost::asio::steady_timer>(io)),
121 muxes(std::make_shared<std::vector<Mux>>())
Feist, Jamesc95cf672019-08-29 16:10:35 -0700122 {
123 }
Feist, Jamesc95cf672019-08-29 16:10:35 -0700124 void run()
125 {
126 file = open(("/dev/i2c-" + std::to_string(bus)).c_str(), O_RDWR);
127 if (file < 0)
128 {
129 std::cerr << "unable to open bus " << bus << "\n";
130 return;
131 }
132
133 if (ioctl(file, I2C_SLAVE_FORCE, address) < 0)
134 {
135 std::cerr << "unable to set address to " << address << "\n";
136 return;
137 }
138
James Feist45772222019-09-27 10:38:08 -0700139 if (!getPresent())
140 {
141 std::cerr << "Cannot detect CPLD\n";
142 return;
143 }
144
145 getBootVer(bootVer);
146 getFPGAVer(fpgaVer);
147 getSecurityRev(securityRev);
148 std::string dbusName = boost::replace_all_copy(name, " ", "_");
Feist, Jamesc95cf672019-08-29 16:10:35 -0700149 hsbpItemIface = objServer.add_interface(
James Feist45772222019-09-27 10:38:08 -0700150 "/xyz/openbmc_project/inventory/item/hsbp/" + dbusName,
Feist, Jamesc95cf672019-08-29 16:10:35 -0700151 inventory::interface);
James Feist45772222019-09-27 10:38:08 -0700152 hsbpItemIface->register_property("Present", true);
Feist, Jamesc95cf672019-08-29 16:10:35 -0700153 hsbpItemIface->register_property("PrettyName", name);
154 hsbpItemIface->initialize();
155
James Feist45772222019-09-27 10:38:08 -0700156 versionIface =
157 objServer.add_interface(hsbpItemIface->get_object_path(),
158 "xyz.openbmc_project.Software.Version");
159 versionIface->register_property("Version", zeroPad(bootVer) + "." +
160 zeroPad(fpgaVer) + "." +
161 zeroPad(securityRev));
162 versionIface->register_property(
163 "Purpose",
164 std::string(
165 "xyz.openbmc_project.Software.Version.VersionPurpose.HSBP"));
166 versionIface->initialize();
167 getPresence(presence);
168 getIFDET(ifdet);
169
170 createDrives();
171
172 runTimer();
173 }
174
175 void runTimer()
176 {
177 timer->expires_after(std::chrono::seconds(scanRateSeconds));
178 timer->async_wait([this](boost::system::error_code ec) {
179 if (ec == boost::asio::error::operation_aborted)
180 {
181 // we're being destroyed
182 return;
183 }
184 else if (ec)
185 {
186 std::cerr << "timer error " << ec.message() << "\n";
187 return;
188 }
189 uint8_t curPresence = 0;
190 uint8_t curIFDET = 0;
191 uint8_t curFailed = 0;
James Feist244f3232019-09-27 15:15:14 -0700192 uint8_t curRebuild = 0;
James Feist45772222019-09-27 10:38:08 -0700193
194 getPresence(curPresence);
195 getIFDET(curIFDET);
196 getFailed(curFailed);
James Feist244f3232019-09-27 15:15:14 -0700197 getRebuild(curRebuild);
James Feist45772222019-09-27 10:38:08 -0700198
199 if (curPresence != presence || curIFDET != ifdet ||
James Feist244f3232019-09-27 15:15:14 -0700200 curFailed != failed || curRebuild != rebuilding)
James Feist45772222019-09-27 10:38:08 -0700201 {
202 presence = curPresence;
203 ifdet = curIFDET;
204 failed = curFailed;
James Feist244f3232019-09-27 15:15:14 -0700205 rebuilding = curRebuild;
James Feist45772222019-09-27 10:38:08 -0700206 updateDrives();
207 }
208 runTimer();
209 });
210 }
211
212 void createDrives()
213 {
214 uint8_t nvme = ifdet ^ presence;
215 for (size_t ii = 0; ii < maxDrives; ii++)
Feist, Jamesc95cf672019-08-29 16:10:35 -0700216 {
James Feist45772222019-09-27 10:38:08 -0700217 bool isNvme = nvme & (1 << ii);
218 bool isPresent = isNvme || (presence & (1 << ii));
219 bool isFailed = !isPresent || failed & (1 << ii);
James Feist244f3232019-09-27 15:15:14 -0700220 bool isRebuilding = !isPresent && (rebuilding & (1 << ii));
James Feist45772222019-09-27 10:38:08 -0700221
222 // +1 to convert from 0 based to 1 based
223 size_t driveIndex = (backplaneIndex * maxDrives) + ii + 1;
James Feist244f3232019-09-27 15:15:14 -0700224 drives.emplace_back(driveIndex, isPresent, !isFailed, isNvme,
225 isRebuilding);
Feist, Jamesc95cf672019-08-29 16:10:35 -0700226 }
227 }
228
James Feist45772222019-09-27 10:38:08 -0700229 void updateDrives()
Feist, Jamesc95cf672019-08-29 16:10:35 -0700230 {
James Feist45772222019-09-27 10:38:08 -0700231
232 uint8_t nvme = ifdet ^ presence;
233 for (size_t ii = 0; ii < maxDrives; ii++)
Feist, Jamesc95cf672019-08-29 16:10:35 -0700234 {
James Feist45772222019-09-27 10:38:08 -0700235 bool isNvme = nvme & (1 << ii);
236 bool isPresent = isNvme || (presence & (1 << ii));
James Feist244f3232019-09-27 15:15:14 -0700237 bool isFailed = !isPresent || (failed & (1 << ii));
238 bool isRebuilding = isPresent && (rebuilding & (1 << ii));
James Feist45772222019-09-27 10:38:08 -0700239
240 Drive& drive = drives[ii];
241 drive.isNvme = isNvme;
242 drive.itemIface->set_property("Present", isPresent);
243 drive.operationalIface->set_property("Functional", !isFailed);
James Feist244f3232019-09-27 15:15:14 -0700244 drive.rebuildingIface->set_property("Rebuilding", isRebuilding);
Feist, Jamesc95cf672019-08-29 16:10:35 -0700245 }
James Feist45772222019-09-27 10:38:08 -0700246 }
247
248 bool getPresent()
249 {
250 present = i2c_smbus_read_byte(file) >= 0;
Feist, Jamesc95cf672019-08-29 16:10:35 -0700251 return present;
252 }
James Feist45772222019-09-27 10:38:08 -0700253
254 bool getTypeID(uint8_t& val)
255 {
256 constexpr uint8_t addr = 2;
257 int ret = i2c_smbus_read_byte_data(file, addr);
258 if (ret < 0)
259 {
260 std::cerr << "Error " << __FUNCTION__ << "\n";
261 return false;
262 }
263 val = static_cast<uint8_t>(ret);
264 return true;
265 }
266
267 bool getBootVer(uint8_t& val)
268 {
269 constexpr uint8_t addr = 3;
270 int ret = i2c_smbus_read_byte_data(file, addr);
271 if (ret < 0)
272 {
273 std::cerr << "Error " << __FUNCTION__ << "\n";
274 return false;
275 }
276 val = static_cast<uint8_t>(ret);
277 return true;
278 }
279
280 bool getFPGAVer(uint8_t& val)
281 {
282 constexpr uint8_t addr = 4;
283 int ret = i2c_smbus_read_byte_data(file, addr);
284 if (ret < 0)
285 {
286 std::cerr << "Error " << __FUNCTION__ << "\n";
287 return false;
288 }
289 val = static_cast<uint8_t>(ret);
290 return true;
291 }
292
293 bool getSecurityRev(uint8_t& val)
294 {
295 constexpr uint8_t addr = 5;
296 int ret = i2c_smbus_read_byte_data(file, addr);
297 if (ret < 0)
298 {
299 std::cerr << "Error " << __FUNCTION__ << "\n";
300 return false;
301 }
302 val = static_cast<uint8_t>(ret);
303 return true;
304 }
305
306 bool getPresence(uint8_t& val)
307 {
308 // NVMe drives do not assert PRSNTn, and as such do not get reported as
309 // PRESENT in this register
310
311 constexpr uint8_t addr = 8;
312
313 int ret = i2c_smbus_read_byte_data(file, addr);
314 if (ret < 0)
315 {
316 std::cerr << "Error " << __FUNCTION__ << "\n";
317 return false;
318 }
319 // presence is inverted
320 val = static_cast<uint8_t>(~ret);
321 return true;
322 }
323
324 bool getIFDET(uint8_t& val)
325 {
326 // This register is a bitmap of parallel GPIO pins connected to the
327 // IFDETn pin of a drive slot. SATA, SAS, and NVMe drives all assert
328 // IFDETn low when they are inserted into the HSBP.This register, in
329 // combination with the PRESENCE register, are used by the BMC to detect
330 // the presence of NVMe drives.
331
332 constexpr uint8_t addr = 9;
333
334 int ret = i2c_smbus_read_byte_data(file, addr);
335 if (ret < 0)
336 {
337 std::cerr << "Error " << __FUNCTION__ << "\n";
338 return false;
339 }
340 // ifdet is inverted
341 val = static_cast<uint8_t>(~ret);
342 return true;
343 }
344
345 bool getFailed(uint8_t& val)
346 {
347 constexpr uint8_t addr = 0xC;
348 int ret = i2c_smbus_read_byte_data(file, addr);
349 if (ret < 0)
350 {
351 std::cerr << "Error " << __FUNCTION__ << "\n";
352 return false;
353 }
354 val = static_cast<uint8_t>(ret);
355 return true;
356 }
357
358 bool getRebuild(uint8_t& val)
359 {
360 constexpr uint8_t addr = 0xD;
361 int ret = i2c_smbus_read_byte_data(file, addr);
362 if (ret < 0)
363 {
364 std::cerr << "Error " << __FUNCTION__ << "\n";
365 return false;
366 }
367 val = static_cast<uint8_t>(ret);
368 return true;
369 }
370
Feist, Jamesc95cf672019-08-29 16:10:35 -0700371 ~Backplane()
372 {
373 objServer.remove_interface(hsbpItemIface);
James Feist45772222019-09-27 10:38:08 -0700374 objServer.remove_interface(versionIface);
Feist, Jamesc95cf672019-08-29 16:10:35 -0700375 if (file >= 0)
376 {
377 close(file);
378 }
379 }
380
381 size_t bus;
382 size_t address;
James Feist45772222019-09-27 10:38:08 -0700383 size_t backplaneIndex;
Feist, Jamesc95cf672019-08-29 16:10:35 -0700384 std::string name;
James Feist45772222019-09-27 10:38:08 -0700385 std::shared_ptr<boost::asio::steady_timer> timer;
386 bool present = false;
387 uint8_t typeId = 0;
388 uint8_t bootVer = 0;
389 uint8_t fpgaVer = 0;
390 uint8_t securityRev = 0;
391 uint8_t funSupported = 0;
392 uint8_t presence = 0;
393 uint8_t ifdet = 0;
394 uint8_t failed = 0;
James Feist244f3232019-09-27 15:15:14 -0700395 uint8_t rebuilding = 0;
James Feist45772222019-09-27 10:38:08 -0700396
397 int file = -1;
398
Feist, Jamesc95cf672019-08-29 16:10:35 -0700399 std::string type;
400
401 std::shared_ptr<sdbusplus::asio::dbus_interface> hsbpItemIface;
James Feist45772222019-09-27 10:38:08 -0700402 std::shared_ptr<sdbusplus::asio::dbus_interface> versionIface;
403
404 std::vector<Drive> drives;
James Feist0b236ab2019-10-02 09:09:16 -0700405 std::shared_ptr<std::vector<Mux>> muxes;
Feist, Jamesc95cf672019-08-29 16:10:35 -0700406};
407
408std::unordered_map<std::string, Backplane> backplanes;
409
James Feist0b236ab2019-10-02 09:09:16 -0700410void updateAssociations()
411{
412 constexpr const char* driveType =
413 "xyz.openbmc_project.Inventory.Item.Drive";
414
415 conn->async_method_call(
416 [](const boost::system::error_code ec, const GetSubTreeType& subtree) {
417 if (ec)
418 {
419 std::cerr << "Error contacting mapper " << ec.message() << "\n";
420 return;
421 }
422 for (const auto& [path, objDict] : subtree)
423 {
424 if (objDict.empty())
425 {
426 continue;
427 }
428
429 const std::string& owner = objDict.begin()->first;
430 conn->async_method_call(
431 [path](const boost::system::error_code ec2,
432 const boost::container::flat_map<
433 std::string, std::variant<uint64_t>>& values) {
434 if (ec2)
435 {
436 std::cerr << "Error Getting Config "
437 << ec2.message() << " " << __FUNCTION__
438 << "\n";
439 return;
440 }
441 auto findBus = values.find("Bus");
442 auto findIndex = values.find("Index");
443
444 if (findBus == values.end() ||
445 findIndex == values.end())
446 {
447 std::cerr << "Illegal interface at " << path
448 << "\n";
449 return;
450 }
451
452 size_t muxBus = static_cast<size_t>(
453 std::get<uint64_t>(findBus->second));
454 size_t driveIndex = static_cast<size_t>(
455 std::get<uint64_t>(findIndex->second));
456 std::filesystem::path muxPath =
457 "/sys/bus/i2c/devices/i2c-" +
458 std::to_string(muxBus) + "/mux_device";
459 if (!std::filesystem::is_symlink(muxPath))
460 {
461 std::cerr << path << " mux does not exist\n";
462 return;
463 }
464
465 // we should be getting something of the form 7-0052 for
466 // bus 7 addr 52
467 std::string fname =
468 std::filesystem::read_symlink(muxPath).filename();
469 auto findDash = fname.find('-');
470
471 if (findDash == std::string::npos ||
472 findDash + 1 >= fname.size())
473 {
474 std::cerr << path << " mux path invalid\n";
475 return;
476 }
477
478 std::string busStr = fname.substr(0, findDash);
479 std::string muxStr = fname.substr(findDash + 1);
480
481 size_t bus = static_cast<size_t>(std::stoi(busStr));
482 size_t addr =
483 static_cast<size_t>(std::stoi(muxStr, nullptr, 16));
484 Backplane* parent = nullptr;
485 for (auto& [name, backplane] : backplanes)
486 {
487 for (const Mux& mux : *(backplane.muxes))
488 {
489 if (bus == mux.bus && addr == mux.address)
490 {
491 parent = &backplane;
492 break;
493 }
494 }
495 }
496 if (parent == nullptr)
497 {
498 std::cerr << "Failed to find mux at bus " << bus
499 << ", addr " << addr << "\n";
500 return;
501 }
502 if (parent->drives.size() <= driveIndex)
503 {
504
505 std::cerr << "Illegal drive index at " << path
506 << " " << driveIndex << "\n";
507 return;
508 }
509 Drive& drive = parent->drives[driveIndex];
510 drive.createAssociation(path);
511 },
512 owner, path, "org.freedesktop.DBus.Properties", "GetAll",
513 "xyz.openbmc_project.Inventory.Item.Drive");
514 }
515 },
516 mapper::busName, mapper::path, mapper::interface, mapper::subtree, "/",
517 0, std::array<const char*, 1>{driveType});
518}
519
520void populateMuxes(std::shared_ptr<std::vector<Mux>> muxes,
521 std::string& rootPath)
522{
523 const static std::array<const std::string, 4> muxTypes = {
524 "xyz.openbmc_project.Configuration.PCA9543Mux",
525 "xyz.openbmc_project.Configuration.PCA9544Mux",
526 "xyz.openbmc_project.Configuration.PCA9545Mux",
527 "xyz.openbmc_project.Configuration.PCA9546Mux"};
528 conn->async_method_call(
529 [muxes](const boost::system::error_code ec,
530 const GetSubTreeType& subtree) {
531 if (ec)
532 {
533 std::cerr << "Error contacting mapper " << ec.message() << "\n";
534 return;
535 }
536 std::shared_ptr<std::function<void()>> callback =
537 std::make_shared<std::function<void()>>(
538 []() { updateAssociations(); });
539 for (const auto& [path, objDict] : subtree)
540 {
541 if (objDict.empty() || objDict.begin()->second.empty())
542 {
543 continue;
544 }
545
546 const std::string& owner = objDict.begin()->first;
547 const std::vector<std::string>& interfaces =
548 objDict.begin()->second;
549
550 const std::string* interface = nullptr;
551 for (const std::string& iface : interfaces)
552 {
553 if (std::find(muxTypes.begin(), muxTypes.end(), iface) !=
554 muxTypes.end())
555 {
556 interface = &iface;
557 break;
558 }
559 }
560 if (interface == nullptr)
561 {
562 std::cerr << "Cannot get mux type\n";
563 continue;
564 }
565
566 conn->async_method_call(
567 [path, muxes, callback](
568 const boost::system::error_code ec2,
569 const boost::container::flat_map<
570 std::string, std::variant<uint64_t>>& values) {
571 if (ec2)
572 {
573 std::cerr << "Error Getting Config "
574 << ec2.message() << " " << __FUNCTION__
575 << "\n";
576 return;
577 }
578 auto findBus = values.find("Bus");
579 auto findAddress = values.find("Address");
580 if (findBus == values.end() ||
581 findAddress == values.end())
582 {
583 std::cerr << "Illegal configuration at " << path
584 << "\n";
585 return;
586 }
587 size_t bus = static_cast<size_t>(
588 std::get<uint64_t>(findBus->second));
589 size_t address = static_cast<size_t>(
590 std::get<uint64_t>(findAddress->second));
591 muxes->emplace_back(bus, address);
592 if (callback.use_count() == 1)
593 {
594 (*callback)();
595 }
596 },
597 owner, path, "org.freedesktop.DBus.Properties", "GetAll",
598 *interface);
599 }
600 },
601 mapper::busName, mapper::path, mapper::interface, mapper::subtree,
602 rootPath, 1, muxTypes);
603}
604
Feist, Jamesc95cf672019-08-29 16:10:35 -0700605void populate()
606{
607 conn->async_method_call(
608 [](const boost::system::error_code ec, const GetSubTreeType& subtree) {
609 if (ec)
610 {
611 std::cerr << "Error contacting mapper " << ec.message() << "\n";
612 return;
613 }
614 for (const auto& [path, objDict] : subtree)
615 {
616 if (objDict.empty())
617 {
618 continue;
619 }
620
621 const std::string& owner = objDict.begin()->first;
622 conn->async_method_call(
623 [path](const boost::system::error_code ec2,
624 const boost::container::flat_map<
625 std::string, BasicVariantType>& resp) {
626 if (ec2)
627 {
628 std::cerr << "Error Getting Config "
629 << ec2.message() << "\n";
630 return;
631 }
632 backplanes.clear();
633 std::optional<size_t> bus;
634 std::optional<size_t> address;
James Feist45772222019-09-27 10:38:08 -0700635 std::optional<size_t> backplaneIndex;
Feist, Jamesc95cf672019-08-29 16:10:35 -0700636 std::optional<std::string> name;
637 for (const auto& [key, value] : resp)
638 {
639 if (key == "Bus")
640 {
641 bus = std::get<uint64_t>(value);
642 }
643 else if (key == "Address")
644 {
645 address = std::get<uint64_t>(value);
646 }
James Feist45772222019-09-27 10:38:08 -0700647 else if (key == "Index")
648 {
649 backplaneIndex = std::get<uint64_t>(value);
650 }
Feist, Jamesc95cf672019-08-29 16:10:35 -0700651 else if (key == "Name")
652 {
653 name = std::get<std::string>(value);
654 }
655 }
James Feist45772222019-09-27 10:38:08 -0700656 if (!bus || !address || !name || !backplaneIndex)
Feist, Jamesc95cf672019-08-29 16:10:35 -0700657 {
658 std::cerr << "Illegal configuration at " << path
659 << "\n";
660 return;
661 }
James Feist0b236ab2019-10-02 09:09:16 -0700662 std::string parentPath =
663 std::filesystem::path(path).parent_path();
Feist, Jamesc95cf672019-08-29 16:10:35 -0700664 const auto& [backplane, status] = backplanes.emplace(
James Feist45772222019-09-27 10:38:08 -0700665 *name,
666 Backplane(*bus, *address, *backplaneIndex, *name));
Feist, Jamesc95cf672019-08-29 16:10:35 -0700667 backplane->second.run();
James Feist0b236ab2019-10-02 09:09:16 -0700668 populateMuxes(backplane->second.muxes, parentPath);
Feist, Jamesc95cf672019-08-29 16:10:35 -0700669 },
670 owner, path, "org.freedesktop.DBus.Properties", "GetAll",
671 configType);
672 }
673 },
674 mapper::busName, mapper::path, mapper::interface, mapper::subtree, "/",
675 0, std::array<const char*, 1>{configType});
676}
677
678int main()
679{
680 boost::asio::steady_timer callbackTimer(io);
681
682 conn->request_name("xyz.openbmc_project.HsbpManager");
683
684 sdbusplus::bus::match::match match(
685 *conn,
686 "type='signal',member='PropertiesChanged',arg0='" +
687 std::string(configType) + "'",
688 [&callbackTimer](sdbusplus::message::message&) {
689 callbackTimer.expires_after(std::chrono::seconds(2));
690 callbackTimer.async_wait([](const boost::system::error_code ec) {
691 if (ec == boost::asio::error::operation_aborted)
692 {
693 // timer was restarted
694 return;
695 }
696 else if (ec)
697 {
698 std::cerr << "Timer error" << ec.message() << "\n";
699 return;
700 }
701 populate();
702 });
703 });
704
James Feist0b236ab2019-10-02 09:09:16 -0700705 sdbusplus::bus::match::match drive(
706 *conn,
707 "type='signal',member='PropertiesChanged',arg0='xyz.openbmc_project."
708 "Inventory.Item.Drive'",
709 [&callbackTimer](sdbusplus::message::message&) {
710 callbackTimer.expires_after(std::chrono::seconds(2));
711 callbackTimer.async_wait([](const boost::system::error_code ec) {
712 if (ec == boost::asio::error::operation_aborted)
713 {
714 // timer was restarted
715 return;
716 }
717 else if (ec)
718 {
719 std::cerr << "Timer error" << ec.message() << "\n";
720 return;
721 }
722 populate();
723 });
724 });
725
Feist, Jamesc95cf672019-08-29 16:10:35 -0700726 io.post([]() { populate(); });
727 io.run();
728}