blob: b2434873c8dc2f1fc31cbc08fb26f06c19089a40 [file] [log] [blame]
Vernon Mauery9e801a22018-10-12 13:20:49 -07001#include "settings.hpp"
2
3#include "xyz/openbmc_project/Common/error.hpp"
4
Tom Joseph19b4f402017-08-02 17:59:30 +05305#include <phosphor-logging/elog-errors.hpp>
6#include <phosphor-logging/log.hpp>
Tom Joseph19b4f402017-08-02 17:59:30 +05307
8namespace settings
9{
10
11using namespace phosphor::logging;
12using namespace sdbusplus::xyz::openbmc_project::Common::Error;
13
14constexpr auto mapperService = "xyz.openbmc_project.ObjectMapper";
15constexpr auto mapperPath = "/xyz/openbmc_project/object_mapper";
16constexpr auto mapperIntf = "xyz.openbmc_project.ObjectMapper";
17
18Objects::Objects(sdbusplus::bus::bus& bus,
Vernon Mauery9e801a22018-10-12 13:20:49 -070019 const std::vector<Interface>& filter) :
Tom Joseph19b4f402017-08-02 17:59:30 +053020 bus(bus)
21{
22 auto depth = 0;
23
Vernon Mauery9e801a22018-10-12 13:20:49 -070024 auto mapperCall = bus.new_method_call(mapperService, mapperPath, mapperIntf,
Tom Joseph19b4f402017-08-02 17:59:30 +053025 "GetSubTree");
26 mapperCall.append(root);
27 mapperCall.append(depth);
28 mapperCall.append(filter);
29 auto response = bus.call(mapperCall);
30 if (response.is_method_error())
31 {
32 log<level::ERR>("Error in mapper GetSubTree");
33 elog<InternalFailure>();
34 }
35
36 using Interfaces = std::vector<Interface>;
37 using MapperResponse = std::map<Path, std::map<Service, Interfaces>>;
38 MapperResponse result;
39 response.read(result);
40 if (result.empty())
41 {
42 log<level::ERR>("Invalid response from mapper");
43 elog<InternalFailure>();
44 }
45
46 for (auto& iter : result)
47 {
48 const auto& path = iter.first;
Tom Joseph7c78adf2017-09-11 12:52:56 +053049 for (auto& interface : iter.second.begin()->second)
50 {
51 auto found = map.find(interface);
52 if (map.end() != found)
53 {
54 auto& paths = found->second;
55 paths.push_back(path);
56 }
57 else
58 {
59 map.emplace(std::move(interface), std::vector<Path>({path}));
60 }
61 }
Tom Joseph19b4f402017-08-02 17:59:30 +053062 }
63}
64
65Service Objects::service(const Path& path, const Interface& interface) const
66{
67 using Interfaces = std::vector<Interface>;
Vernon Mauery9e801a22018-10-12 13:20:49 -070068 auto mapperCall =
69 bus.new_method_call(mapperService, mapperPath, mapperIntf, "GetObject");
Tom Joseph19b4f402017-08-02 17:59:30 +053070 mapperCall.append(path);
71 mapperCall.append(Interfaces({interface}));
72
73 auto response = bus.call(mapperCall);
74 if (response.is_method_error())
75 {
76 log<level::ERR>("Error in mapper GetObject");
77 elog<InternalFailure>();
78 }
79
80 std::map<Service, Interfaces> result;
81 response.read(result);
82 if (result.empty())
83 {
84 log<level::ERR>("Invalid response from mapper");
85 elog<InternalFailure>();
86 }
87
88 return result.begin()->first;
89}
90
Tom Joseph9c60a582017-09-13 17:10:46 +053091namespace boot
92{
93
94std::tuple<Path, OneTimeEnabled> setting(const Objects& objects,
95 const Interface& iface)
96{
97 constexpr auto bootObjCount = 2;
98 constexpr auto oneTime = "one_time";
99 constexpr auto enabledIntf = "xyz.openbmc_project.Object.Enable";
100 constexpr auto propIntf = "org.freedesktop.DBus.Properties";
101
102 const std::vector<Path>& paths = objects.map.at(iface);
103 auto count = paths.size();
104 if (count != bootObjCount)
105 {
106 log<level::ERR>("Exactly two objects expected",
107 entry("INTERFACE=%s", iface.c_str()),
108 entry("COUNT=%d", count));
109 elog<InternalFailure>();
110 }
111 size_t index = 0;
112 if (std::string::npos == paths[0].rfind(oneTime))
113 {
114 index = 1;
115 }
116 const Path& oneTimeSetting = paths[index];
117 const Path& regularSetting = paths[!index];
118
Vernon Mauery9e801a22018-10-12 13:20:49 -0700119 auto method = objects.bus.new_method_call(
120 objects.service(oneTimeSetting, iface).c_str(), oneTimeSetting.c_str(),
121 propIntf, "Get");
Tom Joseph9c60a582017-09-13 17:10:46 +0530122 method.append(enabledIntf, "Enabled");
123 auto reply = objects.bus.call(method);
124 if (reply.is_method_error())
125 {
126 log<level::ERR>("Error in getting Enabled property",
127 entry("OBJECT=%s", oneTimeSetting.c_str()),
128 entry("INTERFACE=%s", iface.c_str()));
129 elog<InternalFailure>();
130 }
131
132 sdbusplus::message::variant<bool> enabled;
133 reply.read(enabled);
134 auto oneTimeEnabled = enabled.get<bool>();
135 const Path& setting = oneTimeEnabled ? oneTimeSetting : regularSetting;
136 return std::make_tuple(setting, oneTimeEnabled);
137}
138
139} // namespace boot
140
Tom Joseph19b4f402017-08-02 17:59:30 +0530141} // namespace settings