blob: a9f98d674be63330d8d692c31fb3a3aa437b9edd [file] [log] [blame]
Gunnar Mills94df8c92018-09-14 14:50:03 -05001#include "config.h"
2
3#include "occ_finder.hpp"
4
Deepak Kodihalli5f031f32017-07-26 08:25:59 -05005#include <algorithm>
Deepak Kodihalli5f031f32017-07-26 08:25:59 -05006#include <experimental/filesystem>
Gunnar Mills94df8c92018-09-14 14:50:03 -05007#include <iterator>
Deepak Kodihalli5f031f32017-07-26 08:25:59 -05008#include <phosphor-logging/elog-errors.hpp>
9#include <phosphor-logging/log.hpp>
Gunnar Mills94df8c92018-09-14 14:50:03 -050010#include <sdbusplus/server.hpp>
Deepak Kodihalli5f031f32017-07-26 08:25:59 -050011#include <xyz/openbmc_project/Common/error.hpp>
Deepak Kodihalli5f031f32017-07-26 08:25:59 -050012namespace open_power
13{
14namespace occ
15{
16namespace finder
17{
18
19using namespace phosphor::logging;
20
21constexpr auto toChar(size_t c)
22{
23 constexpr auto map = "0123456789abcdef";
24 return map[c];
25}
26
Vishwanatha Subbanna3ace7572017-08-22 16:06:11 +053027template <typename T>
Gunnar Mills94df8c92018-09-14 14:50:03 -050028T getDbusProperty(sdbusplus::bus::bus& bus, const std::string& service,
29 const std::string& objPath, const std::string& interface,
Vishwanatha Subbanna3ace7572017-08-22 16:06:11 +053030 const std::string& property)
31{
32 using namespace sdbusplus::xyz::openbmc_project::Common::Error;
33
34 constexpr auto PROPERTY_INTF = "org.freedesktop.DBus.Properties";
35
Gunnar Mills94df8c92018-09-14 14:50:03 -050036 auto method = bus.new_method_call(service.c_str(), objPath.c_str(),
37 PROPERTY_INTF, "Get");
Vishwanatha Subbanna3ace7572017-08-22 16:06:11 +053038 method.append(interface, property);
39
40 auto reply = bus.call(method);
41 if (reply.is_method_error())
42 {
Gunnar Mills94df8c92018-09-14 14:50:03 -050043 log<level::ERR>("Failed to get property",
Vishwanatha Subbanna3ace7572017-08-22 16:06:11 +053044 entry("PROPERTY=%s", property.c_str()),
45 entry("PATH=%s", objPath.c_str()),
46 entry("INTERFACE=%s", interface.c_str()));
47 elog<InternalFailure>();
48 }
49
50 sdbusplus::message::variant<T> value;
51 reply.read(value);
52
53 return sdbusplus::message::variant_ns::get<T>(value);
54}
55
Vishwanatha Subbanna1ec291f2017-08-21 17:07:29 +053056std::vector<std::string> get(sdbusplus::bus::bus& bus)
Deepak Kodihalli5f031f32017-07-26 08:25:59 -050057{
58 namespace fs = std::experimental::filesystem;
59 using Path = std::string;
60 using Service = std::string;
61 using Interface = std::string;
62 using Interfaces = std::vector<Interface>;
63
Deepak Kodihalli5f031f32017-07-26 08:25:59 -050064 auto mapper =
Gunnar Mills94df8c92018-09-14 14:50:03 -050065 bus.new_method_call("xyz.openbmc_project.ObjectMapper",
66 "/xyz/openbmc_project/object_mapper",
67 "xyz.openbmc_project.ObjectMapper", "GetSubTree");
Deepak Kodihalli5f031f32017-07-26 08:25:59 -050068
69 auto depth = 0;
70 Path path = CPU_SUBPATH;
Gunnar Mills94df8c92018-09-14 14:50:03 -050071 Interfaces interfaces{
Vishwanatha Subbanna3ace7572017-08-22 16:06:11 +053072 "xyz.openbmc_project.Inventory.Item",
Gunnar Mills94df8c92018-09-14 14:50:03 -050073 "xyz.openbmc_project.State.Decorator.OperationalStatus"};
Vishwanatha Subbanna3ace7572017-08-22 16:06:11 +053074
Deepak Kodihalli5f031f32017-07-26 08:25:59 -050075 mapper.append(path);
76 mapper.append(depth);
77 mapper.append(interfaces);
78
79 auto result = bus.call(mapper);
80 if (result.is_method_error())
81 {
82 // It's okay to not have inventory, for example at BMC standby
83 return {};
84 }
85
86 using MapperResponse = std::map<Path, std::map<Service, Interfaces>>;
87 MapperResponse response;
88 result.read(response);
89 if (response.empty())
90 {
91 // It's okay to not have inventory, for example at BMC standby
92 return {};
93 }
94
95 std::vector<std::string> occs;
96 for (auto count = 0; count < MAX_CPUS; ++count)
97 {
98 fs::path p(path);
99 p /= std::string(CPU_NAME) + toChar(count);
Vishwanatha Subbanna3ace7572017-08-22 16:06:11 +0530100
101 auto entry = response.find(p.string());
102 if (response.end() != entry)
Deepak Kodihalli5f031f32017-07-26 08:25:59 -0500103 {
Vishwanatha Subbanna3ace7572017-08-22 16:06:11 +0530104 Criteria match{};
105 match.emplace_back(std::make_tuple(
Gunnar Mills94df8c92018-09-14 14:50:03 -0500106 "xyz.openbmc_project.Inventory.Item", "Present", true));
Vishwanatha Subbanna3ace7572017-08-22 16:06:11 +0530107
Deepak Kodihalli3f3fa562017-10-25 04:18:49 -0500108 // Select only if the CPU is marked 'Present'.
Vishwanatha Subbanna3ace7572017-08-22 16:06:11 +0530109 // Local variable to make it readable
110 auto path = entry->first;
111 auto service = entry->second.begin()->first;
112 if (matchCriteria(bus, path, service, match))
113 {
Gunnar Mills94df8c92018-09-14 14:50:03 -0500114 occs.emplace_back(std::string(OCC_NAME) + toChar(count));
Vishwanatha Subbanna3ace7572017-08-22 16:06:11 +0530115 }
Deepak Kodihalli5f031f32017-07-26 08:25:59 -0500116 }
117 }
118
119 return occs;
120}
121
Gunnar Mills94df8c92018-09-14 14:50:03 -0500122bool matchCriteria(sdbusplus::bus::bus& bus, const std::string& path,
123 const std::string& service, const Criteria& match)
Vishwanatha Subbanna3ace7572017-08-22 16:06:11 +0530124{
Gunnar Mills94df8c92018-09-14 14:50:03 -0500125 for (const auto& iter : match)
Vishwanatha Subbanna3ace7572017-08-22 16:06:11 +0530126 {
Gunnar Mills94df8c92018-09-14 14:50:03 -0500127 auto result = getDbusProperty<bool>(
128 bus, service, path, std::get<0>(iter), std::get<1>(iter));
Vishwanatha Subbanna3ace7572017-08-22 16:06:11 +0530129 if (result != std::get<2>(iter))
130 {
131 return false;
132 }
133 }
134 return true;
135}
136
Deepak Kodihalli5f031f32017-07-26 08:25:59 -0500137} // namespace finder
138} // namespace occ
139} // namespace open_power